Professional Documents
Culture Documents
Table of Contents
2
Sitecore Reference Storefront
9.2.1 Vary by Url Path .............................................................................................................................. 34
9.3 Request Caching ................................................................................................................................. 34
9.4 Mini Cart Caching ................................................................................................................................ 35
9.5 Stock Status and Product Prices via Index Files ................................................................................... 35
9.6 Read-only session state support per controller method for improved performance ............................. 36
3
Sitecore Reference Storefront
Chapter 1 Introduction
The Sitecore Reference Storefront is an out-of-the-box storefront solution for building B2C e-commerce
solutions. It has its own separate installation package that contains a webshop, which builds on top of the Sitecore
Experience Platform and Sitecore Commerce powered by Commerce Server or Sitecore Commerce powered by
Microsoft Dynamics.
Both the Microsoft Dynamics and Commerce Server solutions can be found on GitHub:
https://github.com/Sitecore/Reference-Storefront
4
Sitecore Reference Storefront
1.1 License
The solution is licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
In order to contribute as an individual or company, you will have to sign an agreement and get it approved by
Sitecore.
For more information and in order to obtain agreement forms, visit GitHub
5
Sitecore Reference Storefront
The Sitecore Reference Storefront development is based on Microsoft Visual Studio 2013. The solution makes use
of Team Development for Sitecore (TDS) from Hedgehog Development to maintain the storefront Sitecore items
and produce update packages that can later be uploaded to Sitecore.
Before you can build the solution, you will need to copy assemblies from the various platforms into their
respective locations. For more information, see section 2.2
6
Sitecore Reference Storefront
Project Description
Storefront/AX Folder
Commerce.Storefront.ProfileDatabase.sqlproj This represents the SQL project for the Commerce Server profile
database. This creates a DACPAC file that can be used when
setting up the Commerce Server site.
7
Sitecore Reference Storefront
Note
Before getting the source code from the GitHub project, you must make sure the line-ending option is configured
properly for your git client. TDS requires the file to end with a carriage-return + linefeed combination. Failure to
do this will result in the solution not to compile properly.
At the GIT command line, issue the following: git config --global core.autocrlf true
We have supplied a PowerShell CmdLet named UnixToWindoesEOL that can change the line-ending in case the
above command was not issued beforehand. It takes a root path and a file pattern (include filter) like “*.item” as
parameters
Furthermore, in this release a new .gitattribute was added specifically to stop GIT from transforming *.item files.
Pre-requisites
The solution makes use of Team Development for Sitecore (TDS) from Hedgehog Development version
5.5.19.
Microsoft Visual Studio 2015 or later is required. Note that only VS 2015 has been tested.
.Net framework version 4.52.
Commerce Server has been installed as the project assembly references use the GACed version of the
libraries.
The outcome is a series of update packages that can be deployed on a SCpbCS installation.
8
Sitecore Reference Storefront
The common update package is located in: \Common\TDSCommon_Master\Package_Debug.
The outcome is a series of update packages that can be deployed on a SCpbMD installation.
9
Sitecore Reference Storefront
Note:
The StorefrontManager resolves the CurrentStorefront via the Sitecore Site
node configuration element defined in Commerce.Storefront.config file.
The hostName attribute must be set to the web site host header defined in
IIS. Sitecore will automatically resolve the Sitecore.Context.Site property and the StorefrontManager combines
the Site.RootPath and Site.StartItem to locate the Home node for the CommerceStorefront.
2.3.3 Knockout.js
Views requirering dynamic and responsive refresh of the data make use of Knockout.js bindings to fulfill their
content. Let’s take the cart page as an example. When the Index() method of the CartController is called,
Knockout bindings and labels are setup in the cshtml view, that’s it! When the view has rendered into the
browser, a Javascript call is made to get the current cart data (in Json format) that is automatically bound to the
view.
10
Sitecore Reference Storefront
Many of the Storefront pages follow this pattern.
Clicking on the ShoppingCart item (as shown above) reveals it’s label data. The views target those fields during
the rendering process. For example, to get the Total Label the following call in made in the view:
Note:
Managers are automagically injected into the controller constructors via Castle Winsor.
11
Sitecore Reference Storefront
var response = this.CartManager.GetCurrentCart(CurrentStorefront,
CurrentVisitorContext, false);
CSCartBaseJsonResult cartResult = new
CSCartBaseJsonResult(response.ServiceProviderResult);
if (response.ServiceProviderResult.Success && response.Result != null)
{
cartResult.Initialize(response.Result);
}
This controller action is responsible for returning the current user’s cart to the caller in a standardized Json format.
The method calls CartManager.GetCurrentCart(). In turn, the manager calls the Connect API and returns it to the
controller in the form of a ManagerResponse. The full Connect result context is accessible, allowing to inspect the
return value of the connect call for errros and messages while allowing direct access to the predominant object of
the call via the Result property.
The following is the method signature of the GetCurrentCart() method.
Note:
Input into managers always take the CurrentStorefront and CurrentVisitorContext. As shown in the
GetCurrentCart() code, the base controller class supports convenience methods to retrieve the information.
The ManagerResponse exposes both the CartResult object of the Connect API call (via the ServiceProviderResult
property) as well as the CommerceCart it returned (via the Result property).
The last part of the GetCurrentCart method returns the cart in a Json format. Notice the Storefront makes use of
classes which sets up the necessary properties that are serialized into the response1.
1 In the future the Json class initialization pattern will change. See Chapter 6 for more
information.
12
Sitecore Reference Storefront
13
Sitecore Reference Storefront
2.4.1 Resolving Category and Product Presentation via the Shop Item
The Storefront makes use of the Sitecore “*” notation to provide the presetation detail information of category
and product. First let’s look at the url format generated by the Storefront.
Note:
Urls are generated via the Sitecore LinkManager. The Reference Storefront Common library provides a
CatalogLinkProvider that generates the category and product urls.
The following shows how the Shop item are defined in Sitecore:
The first “*” under Shop defines the presentation details of the categories and the second level “*” defines the
presentation details of the products.
14
Sitecore Reference Storefront
2.5 Checkout
The Reference Storefront checkout is currently defined in a single view containing 3 tabs. Everything is controlled
via JavaScript and Knockout.js bindings.
When the checkout view is loaded, a Javascipt call is made to retrieve all of the data required to handle the
checkout process. The following CheckoutController action is called: GetCheckoutData
Note:
The returned JSON contains direct Connect, CS Connect or AX Connect entity references. This will change in the
near future to have independent JSON return classes.
The returned data contains the current cart, Shipping Options (global and per line), Payment Options and
Payment methods, etc… You can use a tool like Fiddler to intercept the calls and see what exactly is returned in
the JSON response.
15
Sitecore Reference Storefront
16
Sitecore Reference Storefront
The Reference Storefront support the ability to define multiple storefronts (of the same platform) in the same
Sitecore instance.
Using controller renderings instead of view renderings in one key component (see Do Controller Renderings -
Don't do View Renderings).
Controllers support base class methods that will build the path to the view based on the current storefront.
As metioned earlier, the Sitecore Site element is used to identify the current storefront being browsed. Different
host headers should be defined for each of the storefronts. The host header is key to identifying the current
Storefront.
Also mentioned earlier is the use of: StorefrontManager.CurrentStorefront to access Storefront specific
configuration information.
3 If you want, you can setup MyStorefront to use the original Adventure Works Catalog.
17
Sitecore Reference Storefront
a. Add MyStorefront Catalog to the selected catalogs under \Sitecore Commerce\Catalog
Management\Catalogs
b. Copy the existing Storefront site and rename the copy to MyStorefront
c. Update MyStorefront/Home node Catalog property to use "MyStorefront Catalog"
d. Update the MyStorefront/Home/Product catalog node CategoryDatasource property to
point to /sitecore/Commerce/Catalog Management/Catalogs/MyStorefront
Catalog/Departments
e. Update all the items under the MyStorefront/Global node to point to the MyStorefront
Storefront site
f. Update all the pages presentation details under MyStorefront/Home node (including Home)
so the rendering data sources are pointing to the MyStorefront Storefront site
2. Open the Sitecore/System/Marketing Control Panel/Engagement Plans/CommerceConnect node.
a. Copy the existing AE plans and rename them to start with MyStorefront
b. Deploy the new plans
3. Publish and index
18
Sitecore Reference Storefront
b. Add new bindings to the Sitercore site for ports 80 and 443 with host name
ax.reference.fabrikam.com
2. Add the new host name to the HOSTS file
127.0.0.1 ax.reference.fabrikam.com
3. Open [inetpub path]\Website\App_Config\Include\DynamicsRetail.Connectors.Services.config file
a. Add an endpoint for each of the existing endpoints (Contoso's endpoints). The endpoint's
addresses have to point to the Fabrikam's Transaction Service and the names have to end in
"_[channelID]", where Channel ID is Fabrikam's channel id (5637145359).
4. Open Commerce Server Catalog Manager and import Fabrikam's catalog
5. Open [inetpub path]\Website\App_Config\Include\ Reference.Storefront \Reference.config
a. Make a copy of the Site node.
i. Set name = Fabrikam
ii. Set rootPath = “/sitecore/content/Fabrikam”
iii. Set domain = “CommerceUsersFabrikam”
iv. Set hostname = “ax.reference.fabrikam.com”
6. Open [inetpub path]\Website\App_Config\Security\Domains.config file and add the following domain
<domain name="CommerceUsersFabrikam" ensureAnonymousUser="false" />
7. Open [inetpub path]\Website folder
a. Make a copy of [inetpub path]\Website\Views\Storefront and rename it to Fabrikam
Now we are ready to start setting things up in Sitecore. Navigate to the Sitecore site and login
1. Open Content Editor
a. Add Fabrikam's catalog to the selected catalogs under \Sitecore Commerce\Catalog
Management\Catalogs
b. Copy the existing Storefront site and rename the copy to Fabrikam
c. Update Fabrikam/Home node Catalog property to use "Fabrikam Base Catalog"
d. Set the Fabrikam/Home node Channel property to Fabrikam's channel id (5637145359)
e. Update the Fabrikam/Home/Product catalog node CategoryDatasource property to point to
/sitecore/Commerce/Catalog Management/Catalogs/Fabrikam Base
Catalog/Departments/22565426194
f. Update all the items under the Fabrikam/Global node to point to the Fabrikam Storefront site
g. Update all the pages presentation details under Fabrikam/Home node (including Home) so the
rendering data sources are pointing to the Fabrikam Storefront site
2. Open the Sitecore/System/Marketing Control Panel/Engagement Plans/CommerceConnect node
a. Copy the existing AE plans and rename them to start with Fabrikam
b. Deploy the new plans
3. Publish and index
19
Sitecore Reference Storefront
2.7 Security
Self-Signed Certificates
For development purpose, you will need to setup a self-signed certificate if you desire to run the Storefront in
HTTPS. The following link will bring you to a Microsoft page that shows you how this is done:
https://technet.microsoft.com/en-us/library/cc753127(v=ws.10).aspx
Disabling HTTPS
The Sitecore.Storefront.config file contains a settings value if you need to disable HTTPS for development
purpose.
<settings>
<setting name="Storefront.EnforceHTTPS" value="true"/>
</settings>
Simply set the value to false and the enforcing of HTTPS will be disabled.
Note
The AX Checkout control does not yet understand this flag and will currently always enforce HTTPS.
Attribute Description
HttpPost Base on security best practices, all Ajax API methods should be done via HTTP
POST instead of GET. Even for method that simply return values.
Authorize This should be used when the Ajax call needs to be performed by an authorized
user. Anonymous calls are automatically rejected.
20
Sitecore Reference Storefront
Attribute Description
ValidateJsonAntiForgeryT By validating the anti-forgery token, we protect the site from Cross Site Request
oken Forgery. For more information, please follow this link:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
OutputCache(NoStore = This ensures the results are not cached by the browser, server or any other device.
true, Location =
OutputCacheLocation.No https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Web_Co
ne) ntent_Caching
21
Sitecore Reference Storefront
2.8 Miscellaneous
2.8.1 ProductItemResolver
The ProductItemResolver processor of the <httpRequestBegin> pipeline is used to resolve the current Sitecore
catalog item (Category or Product) by examining the Url and the defined route data. When a Catalog item is
identified, it sets the following ISiteContext parameters:
CurrentCatalogItem
UrlContainsCategory
This allows the Reference Storefront code to know when the current url represents a CatalogItem.
2.8.2 CatalogLinkManager
In conjunction with the Sitecore LinkManager.GetDynamicUrl() method, the CatalogLinkManager is responsible
for generating all of the catalog item urls. The following shows how it is specified in the
Reference.Storefront.config file:
<linkManager defaultProvider="sitecore">
<patch:attribute name="defaultProvider">commerce</patch:attribute>
<providers>
<add name="commerce"
includeFriendlyName="true"
useShopLinks="true"
includeCatalog="false"
type="Sitecore.Reference.Storefront.SitecorePipelines.CatalogLinkProvider,
Sitecore.Reference.Storefront.Common"/>
</providers>
</linkManager>
Note
The Sitecore attributes are not shown in the XML configuration as we only describe the attributes that are specific
to the Reference Storefront.
Parameter Description
includeFriendlyName Tells the link manager to include the product or category display name as part of the
url.
useShopLinks When true, the link manager will generate urls that fall under the “shop” item of the
Storefront Home item.
When false, it generates urls that either fall under the Category or Product items of the
Storefront Home item.
includeCatalog When true, the catalog name is added as part of the url.
Direct Links
The Reference Storefront allows direct links to items found under the “Product Catalog” item of the storefront
Home item. When the CatalogLinkManager detects direct links, it will end up generating direct links
automatically. For example, if a direct link is used to browse a category, all products within that category will be
direct links as well. When a direct link is used on a product, the product recommendations will be direct links.
22
Sitecore Reference Storefront
Note
If you rename the “Product Catalog” storefront Home item, you will need to change the code to recognize the
new name. The constant is found in ProductItemResolver.NavigationItemName. Renaming this will
automatically adjust the Route table.
23
Sitecore Reference Storefront
The control properties define a Data Source that points to an item (Recommended Products) that in turn define
the Named Searches to be applied. Two types of named searches are supported:
1. Search based
2. Static
A Search based named search defines the Sitecore query that will be applied to locate the products to be
displayed.
Notes
The current version of the system does not validate that only catalog items (category & product) can be selected.
If you add any other type of item, the Reference Storefront will fail to render the home page.
24
Sitecore Reference Storefront
The master branch always has the latest code. In the above example, master is the same as
releases/8.0.0/master. Bug fixes to previous version are made in the version specific branch. These changes are
25
Sitecore Reference Storefront
never merged into master. Bug fixes to the current version are done in the version specific branch and merged
into master.
26
Sitecore Reference Storefront
27
Sitecore Reference Storefront
To improve indexing performance, you may want to remove the indexing of the product
inventory information. This can be done by removing the pipeline processor defined in the
<commerce.inventory.stockStatusForIndexing> pipeline.
This can be achieved by using a standard <patch:delete> element in one of the existing Sitecore
Reference Storefront configuration file.
<commerce.inventory.stockStatusForIndexing>
<processor
type="Sitecore.Commerce.Connect.DynamicsRetail.Pipelines.Inventory.StockStatu
sForIndexing, Sitecore.Commerce.Connect.DynamicsRetail">
<patch:delete/>
</processor>
</commerce.inventory.stockStatusForIndexing>
28
Sitecore Reference Storefront
This section refers to how the Reference Storefront looks for Product prices when displaying
product lists either on the category page or on the related product section of the Product Detail
Page (PDP). From an API perspective, we focus on the GetProductBulkPrices API configuration.
The index may provide a significant performance boost in some cases when retrieving and
displaying lists of products.
The PDP always looks up the current product price via the live Connect API.
When the UseProductBasePriceAsVariantPrice flag is set to <true>, the variant price will be the one defined at the
product level. When set to <false>, the actual variant price is returned.
29
Sitecore Reference Storefront
Sitecore.Commerce.Connect.CommerceServer">
<patch:delete/>
</processor>
</commerce.prices.getProductBulkPrices>
The above will use the version of the GetProductBulkPrices API that retrieves price information from the index.
One more configuration must be added to indicate that we need to index the variant pricing. The following must
be added to the <fields> section of the Reference.Storefront.Index.Lucene.config file.
<field fieldName="VariantInfo"
returnType="string">Sitecore.Reference.Storefront.Search.ComputedFields.VariantInfoComputedField,
Sitecore.Reference.Storefront.Powered.by.CommerceServer</field>
<commerce.prices.getProductBulkPrices patch:source="Sitecore.Commerce.Prices.config">
<processor type=
"Sitecore.Commerce.Connect.DynamicsRetail.Pipelines.Prices.GetProductBulkPrices,
Sitecore.Commerce.Connect.DynamicsRetail">
<patch:attribute name="type">
Sitecore.Reference.Storefront.Connect.Pipelines.Prices.GetProductBulkPricesFromIndex,
Sitecore.Reference.Storefront.Powered.by.Microsoft.Dynamics</patch:attribute>
<param ref="entityFactory"/>
</processor>
<processor type=
"Sitecore.Commerce.Connect.CommerceServer.Catalog.Pipelines.GetProductBulkPrices,
Sitecore.Commerce.Connect.CommerceServer">
<patch:delete/>
</processor>
</commerce.prices.getProductBulkPrices>
One more configuration must be added to indicate that we need to index the variant pricing. The following must
be added to the <fields> section of the Reference.Storefront.Index.Lucene.config file.
<field fieldName="VariantInfo"
returnType="string">Sitecore.Reference.Storefront.Search.ComputedFields.VariantInfoComputedField,
Sitecore.Reference.Storefront.Powered.by.Microsoft.Dynamics</field>
30
Sitecore Reference Storefront
By default, both Commerce Server and Microsoft Dynamics AX versions of the Storefront
retrieve the stock status information from the index.
This can be easily configured by editing the home item of the storefront in the content editor as
shown below:
31
Sitecore Reference Storefront
Note
French is not defined as Tier-1 language in Sitecore and hence has no corresponding language file for download,
but it is still automatically created by CS Connect upon site startup.
As of Sitecore version 8.1, language fallback is natively supported. For more information on this new feature,
please follow this link:
https://doc.sitecore.net/sitecore_experience_platform/language_fallback/language_fallback
The Reference Storefront has been fully tested to make sure item level language fallback is fully supported. To
enable the feature, the Reference.Storefront.config file needs to be modified in the following manner:
<sites>
<site name="storefront" patch:before="site[@name='website']"
virtualFolder="/"
physicalFolder="/"
rootPath="/sitecore/content/storefront"
startItem="/home"
database="web"
domain="extranet"
allowDebug="true"
cacheHtml="true"
htmlCacheSize="10MB"
enablePreview="true"
enableWebEdit="true"
enableDebugger="true"
disableClientData="false"
requireLogin="false"
hostName="cs.reference.storefront.com"
contentLanguage="en"
content="master"
language="en"
ItemNotFound="/error/404"
enableTracking="true"
enableItemLanguageFallback="false"
enableFieldLanguageFallback="false"
/>
32
Sitecore Reference Storefront
<site name="shell">
<patch:attribute name="enableItemLanguageFallback">true</patch:attribute>
</site>
<site name="website">
<patch:attribute name="enableItemLanguageFallback">true</patch:attribute>
</site>
</sites>
The enableItemLanguageFallback attribute of the “storefront” site enables the feature in the storefront, while the
“shell” & “website” enables it in the content editor.
33
Sitecore Reference Storefront
Chapter 9 Performance
The Reference Storefront has been tuned to offer maximum performance under load. This has
been achieved through the various techniques described below.
By including the language, this allows to cache renderings by including the currently selected user language. Very
useful for sites operating in multiple languages. For an example, see the ProductInformation storefront rendering.
In this scenario, it is possible for more than one rendering of the same presentation detail to request similar
information. The Reference Storefront makes use of request caching to make sure that queries for catalog items
are only performed once per http request, therefore does not penalize site performance over granularity of the
presentation detail controls.
34
Sitecore Reference Storefront
Figure 4 - Product Presentation Details
In the example product presentation details shown above, the controls boxed in red all share the same
information. Request caching is used to make sure only a single query is performed to retrieve the product
information.
This is done by using a cookie that acts as an indicator telling the web server when it is ok to retrieve the cart from
the ECS. When the cart is modified, the cookie is removed and on the next call for the mini cart, the cart is
retrieved and the cookie is re-created.
In some cases, using the index file can provide an important performance boost over calling the API which
perform direct lookups in the ECS. You need to be aware that if these options are enabled, your indexing time will
increase as extra time will be required to save this information in the index.
35
Sitecore Reference Storefront
9.6 Read-only session state support per controller method for improved
performance
By design, ASP.NET session state is set to Required by default to allow session content to be both read and
updated (read-write). In the Sitecore Experience Platform (SXP), both contacts and interactions are loaded into
session state, which means that any attempt to update the contact or add experiences to the interaction requires
write access. When multiple requests try to access the session content concurrently, they will by default be
queued up as only one thread can update the session content at any given point in time.
Modern websites load a page asynchronously using AJAX technology as part of improving the user experience. By
returning the minimal amount of HTML immediately, it’s possible for the browser to partially render the page at
the earliest possible time. Pages that involves retrieval of data will be able to partially render the page without
having to wait until all data have been retrieved and thereby provide a rapid response to the visitor. By executing
multiple requests in parallel it will potentially speed up the retrieval of data and the total page load time will be
decreased. In the Reference Storefront, a page like My Account, which gives an overview of the visitor’s order
history, active wish lists, customer addresses and loyalty programs, the content for the individual sections are
requested in parallel as individual AJAX calls. Including the main page, mini-cart, and VisitorIdentification
(required SXP specific call), that amounts to 7 simultaneous HTTP requests for the page to fully load the HTML
and data. If images, CSS and scripts are included, it amounts to more, but these artifacts are usually cached both
in the browser and at the IIS and presents less of a problem.
HTTP requests that are not updating the session, including not updating the contact or interaction through the
use of the SXP API, can be executed with session state set to read-only, thereby allowing the requests to be
unblocked and executing in parallel to improve page load time and page throughput.
The effect is most apparent in case of long running AJAX requests like retrieving order history, active wish lists
etc. which retrieves data from the external commerce system.
In ASP.NET MVC it’s possible to set the session state per controller. By using an IOC container like Windsor-Castle
and by overriding method GetControllerSessionBehavior for setting SessionStateBehavior, it’s possible to
set it for each controller method being called. The advantage is a more fine grained configuration without having
to split up controller methods that logically belongs together.
In version 8.2, a new setting “Storefront.ReadOnlySessionStateBehaviorEnabled” has been introduced in file
“/App_Config/include/Reference.Storefront/Reference.Storefront.config” with default value set to false:
In version 8.2 of the storefront, a new attribute StorefrontSessionState has also been introduced
[StorefrontSessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
If a method is augmented with the attribute having SessionStateBehavior set to ReadOnly, the method gets
called with read-only access to session content, meaning it can be executed in parallel. The rest of the controller
methods gets the default access.
36
Sitecore Reference Storefront
As example, the controller Sitecore.Reference.Storefront.Controllers.AccountController contains
method AddressList, which is augmented with the attribute:
/// <summary>
/// Address Book in the Home Page
/// </summary>
/// <returns>The list of addresses</returns>
[HttpPost]
[Authorize]
[ValidateJsonAntiForgeryToken]
[OutputCache(NoStore = true, Location = OutputCacheLocation.None)]
[StorefrontSessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public JsonResult AddressList()
{
37