We had a requirement on a project to pre-populate a commerce test customer for our dev environment. Whenever the website was first loaded, a test user should be pre-added. In our scenario, the customer had a number of extra properties like had signed up to the newsletter etc..
On a lot of projects, people would update the commerce object via the business foundation manager within commerce, but this rules out the intergeneration we required. Instead, the classes within the business Foundation manager can be updated in two ways. In commerce, all the business foundation objects can be accessed using the DataContext.Current.MetaModel API. In the MetaModel, there is a property called MetaClasses that you can use to get access to the custom business foundation objects.
All of these objects can be updated via code which is very handy. Some examples of the objects you may find in MetaClasses are RecentReferenceHistory, Customer, Organization, Address, CreditCard, ContactNote, CustomizationItem, CustomizationItemArgument, CustomPage, Folder, FolderElement, ImageFolderElement, PdfFolderElement, CountryExtended So, to get a business foundation class we can use several approaches. First, we need to get the business foundation object itself: We can do this by either using:
I prefer using GetMetaClass() as it throws an exception if the class doesn't exist, which makes life a lot easier when trying to debug. When the commerce update fails silently, it can be really hard to figure out where the issue occurred. The next step is to add the fields:
After you have a reference to the customer property, you can use its CreateMetaField method to create the new properties (you may also want to check that it doesn't already exist). I would recommend using CreateMetaField but you can also use MetaFieldBuilder, the below code does the same thing:
An alternative approach, if you want to deal with multiple business items, is to iterate through the collection:
When we came to implement this in our solution, we added the code into an InitializationModule and we found that the DataContext.Current was not initialized correctly. If you use the code above and it doesn't work, try moving your code out of the InitializationModule. I found a useful forum post that said to add:
After a bit of trial and error, it seems that commerce migration script also creates the business foundation scripts which create the commerce objects. If you try getting the business foundation classes before this runs, then they will always be null.
In today's tutorial we've talked about the Episerver commerces MetaClasses, in particular, the Customer class. We've gone over two methods to add custom properties to the class via code. One using the CreateMetaField on the customer object itself, the other using the MetaFieldBuilder class to add a property.
Hey, folks. When we work with the basket in Episerver commerce, it is quite likely you may need to store some custom data against a line item. This might be the image of the product, the discount applied to it etc... In commerce manager you can do this with the GUI, however, you can also add custom properties to the LineItem class via code.
On a recent project, we had a requirement to pre-populate the whole Episerver and Episerver commerce database on first website load for the developer's environment set-up. Having the ability to trash your database and re-build it can be a very useful for development, however, before you go running off and creating your own fixtures, I will warn you there is a lot of overhead to create the code.
In this scenario, an extra property which will call "Custom Property" for shits and giggles was needed to be added onto the LineItem class. After a quick Google, I struggled to find any documentation on this but it can be done using the metadata plus API. Using this API and the OrderContext you can add as many custom properties as you want against LineItems, as shown:
I've simplified this code snippet to make it easier to read. First, we use OrderContext.Current.PurchaseOrderMetaClass to get the MetaClass. This is the class that will save our property. Next, we use OrderContext.MetaDataContext to get the metadata context. After that, it's simply using MetaField to create the property and then metaClass.AddField to save it. You can then access your property using the following snippet:
In today's guide, we've talked about how to extend the LineItem class. This can be done either via the commerce manager or code. When working with code you will need to look in the Mediachase.Commerce.Orders namespace for OrderContext.Current.PurchaseOrderMetaClass and OrderContext.MetaDataContext. Using MetaField.Create() you can then add in whatever properties you may need.
When you use commerce after someone signs-up using the membership provider, you may want to create your own commerce user to store custom data. For example, on one project when you signed up, you had to supply your date of birth and a newsletter opt-in. As this is profile information rather than authentication data, a membership provider doesn't provide the methods to update profile information, and nor should it.
Instead, one solution is to stop everything you need as a commerce customer. To get started saving your customer's details into commerce, you need to call 'CustomerContact.CreateInstance(membershipUser)'. If you don't do this and try to manually create a new customer, Epi will create two commerce customers which you definitely don't want. In this project, we wanted to unit test a lot of the customer and authentication code, so to make this unit testable, I have wrapped the code into a CustomerContactHelper with an interface so it can be swapped out in a test library if required.
After this, you need to update your data into the customer object. Out of the box commerce comes with a number of default properties like First Name, Last Name but, in my circumstance, there was no default Newsletter opt-in. Adding a property doesn't involve that much code luckily.
I wrote an article how to do this called Adding a custom field into the Commerce Customer Object via code After you have added all the data you require into your commerce customer, you then need to call customerContact.SaveChanges() method to persist it back to the database.
I have wrapped the save method in the call above so we can unit test the code in question. If you try to call SaveChanges() out of a commerce context you will get an ActivationException so I had to wrap it in a try/catch. That's it! You can now create your own commerce customers via code!
If you need to get the root catalogue node in Episerver commerce, you can use the ReferenceConverter API to get a link to the catalogues defined in your project, as follow.
You can then filter the catalogue you want via the Name property, e.g.
A key aspect of many websites is building an on-line community. In today's guide, I'm going to quickly cover how to get your customer information from Episerver commerce.
Getting a user with the Membership User
The easiest way to get a user is to use the GetContactForUser method and pass in a MembershipUser. You can call Membership.GetUser(username) to get the user and then you simply pass this into the CustomerContext to get the user.
Getting a user when you can't use Membership User
Episerver has also provided another way to access a commerce customer. I've had a few times when I've been searching for users in an admin page when I can't create a MembershipUser. However, there is a slight issue within. I tried calling the overload of GetContactByUserId which takes a string username but, unfortunately, it never returned anything. I looked at the commerce database in the cls_Contact table, as shown below and you can see the word "String:" is appended in-front of the username.
If you pass in the value "String:" as your username, it will return you a valid CustomerContact
I had a requirement in one of my Epi-Commerce projects that whenever a website visitor signed up to the website and created an account, that account was locked to the default currency for their current location. This could not be changed as it could potentially allow people to get items at a discounted rate. In a normal scenario, to get the current currency you would normally use the Epi Commerce SiteContext instance and use the Currency property, however, by default this uses a cookie and we had security concerns that a user might be able to cheat the system by changing the currency in their cookie.
Instead, we thought it would be a better approach to use a session value and store the currency when it was needed. My initial thought was to stick some code in the base page and product controller and bypass the Epi API altogether, however, this approach definitely wasn't ideal. Firstly, all the developers in the team would have to remember to not use some of the Epi API calls (which in a big team was very unlikely to happen) and, worse, it would also mean we wouldn't be able to use some parts of the Epi API. The approach we finally decided upon was to create our own project based SiteContext that inherited from the Epi SiteContext and in the initialisation module tells structure map to use my custom version instead of the Epi version.
Intercepting the request this way allowed me to contain all my code in one area and allowed the Epi API to carry on doing its thing while the other dev's on the project could carry on working, oblivious to the way it worked had changed. Perfect! In our situation we had two ways the currency could be set: Anonymous users: Should use the default currency set for their location.
The code to do this was done in a GeoLocation helper. Based on their current IP a currency code will be returned. We then had a currency repository that we could throw the country code at and we would get back the default currency for that location Logged In users: Should always use the currency stored against their user account. In our case, this was a third party customer service.
When a site user logged in, the currency returned should be set based on this value After we had the correct currency to display, I then stored the value in session state so it didn't have to do the costly look-up again. This was done using MemoryCache stored against either the HttpContext.Current.Request.AnonymousID value for anonymous users, or the ProviderKey from the MembershipUser class for logged in users.
Memory Cacher Class
The above code will allow you to add and remove items from the global cache. The next part is creating your Custom SiteContext
The last part of the puzzle is to configure structure map.
Now that Episerver has pushed everything to use Nuget, installing Episerver commerce is extremely easy. First, you need to install the Episerver Visual Studio project extension. http://world.episerver.com/documentation/Items/Installation-Instructions/installing-episerver/ This extension will create you a brand new Episerver web project with all the required Nuget packages pre-installed for you. You need to download Visual Studio extension. You can create empty or template projects and do custom development on it.
After that you can create your Visual Studio MVC project
Next, you need to make sure you have the NuGet Package Manager installed with the Episerver feed installed in the source manager, "http://nuget.episerver.com/feed/packages.svc/". first, open up the Nuget settings page:
And Add the EPi Feed.
To install commerce, right click on your solution and select Manage Nuget Packages for the solution, you should see an Episerver feed in the right. Select it and search for commerce.
Install the feed, build your project and you're done For more information have a look on Epi World http://world.episerver.com/documentation/Items/Installation-Instructions/installing-episerver/
I was recently doing some product content migration for a recent project and part of the import data also included the products metadata/SEO properties for the web page like title, description and keywords tags. I started my import job and, about halfway through, it threw an exception that the MaxLength of the description property had been hit:( When you work with commerce entities like products, variant, catalogues you will have to have an object that inherits from EntryContentBase.
Within EntryContentBase is an object called SeoInformation, which I was using to store the products pages meta data. As SeoInformation has a max limit and some of our product descriptions were auto-generated, my life became a lot more confusing. I'm still a bit confused why there is such a small a cap on the description field so we had to come up with a workaround. Obviously, having two sets of meta-data properties for a content editor is confusing and pretty naff. In this instance, as I couldn't use SeoInformation, my only option was to hide SeoInformation from content editors and create a new set.
In Episerver, we can use the [ScaffoldColumn] attribute to hide things from the content editors. As SeoInformation can't be removed from EntryContentBase, it's the only option. In your product and variant definitions override SeoInformation and apply the attribute.
Do not use the [Ignore] attribute instead of as well as [ScaffoldColumn] because EPiServer will not let content editors publish pages, instead, they will get the following error: 'Property with name 'SeoInformation' is not part of the ContentType definition'. Now we have hidden SeoInformation, the next step was to define my own metadata properties:
On the product and variant layout, I then used these properties instead of the out of the box ones Due to a silly character limit in commerce, you may not be able to use the out of the box SeoINfomration object defined within EntryContentBase. To get around this limitation we hide SeoInformation from content editors using [ScaffoldColumn] and create our own version.
When we recently upgraded to Episerver Commerce Manager to Commerce 8 and whenever we tried to view commerce manager, we kept getting a 'Virtual path to protected packages is invalid: ''.' error, like so:
The fix was to remove all traces of EPiServer.Packaging.dll and EPiServer.Packaging.UI.dll from your commerce project.
YOU ONLY DO THIS IN YOUR COMMERCE PROJECT.
First, you need to remove the files in 'modules\_protected' it's best to make a file copy of anything you delete as it can be a pain to get them back. Most of these files are needed by the Episerver Ui to run.
The next step was to remove the references from the project itself:
After this, the last step was to check both the dll's had been removed from the bin directory. A bit more information about this unsuccessful removal of EPiServer UI Add-ons if not successfully removed can be found within this tutorial, Changes to package locations
NOTE: THIS POST WAS WRITTEN WHEN PROMOTIONS WAS IN BETA. THE CODE CHANGED SLIGHTLY WHEN IT WAS REALISED INTO PRODUCTION
With the release of Episerver commerce 8.12.0 comes a new beta feature for managing promotions and orders. From my initial look, the new system seems a lot more flexible than the old version. Aside from providing extra functionality to promotions, one of the immediate advantages of using this new approach is that that the API components have been developed to abstractionist allowing us as developers to be able to unit test commerce a lot more easily. There are quite a few advantages of using the new features including The ability to completely bypass having to store your ordering data within commerce.
If, for example, you have your own custom ordering service and your own custom admin screens to view and edit orders, historically, you still had to store this data within commerce. If you don't need to access your order data from within commerce, then there's not a lot of point writing the code to integrate with it. Using the new API you can create your own implementation of the order repository.
Removing the overhead of storing the order information twice, in your custom service and in commerce The ability to completely remove the current commerce workflow from your project entirely. This means you can even create your own baskets and, at checkout, apply the logic in your own code without having to customise the Episerver workflow classes. This also means you could use something like Reddis to manage your cart data and completely get rid of some of the nastier commerce API calls like the CartHelper.
Historically, unit testing Episerver commerce has been pretty tough and frustrating as none of the major API's have been written to abstractions. CartHelper, for example, was a massive pain to get under a test harness. In order to get the cart helper, I had to create a wrapper around it and the basket helper and the cart itself just to be able to write a few simple tests to check that products can be added to the basket successfully. With the new order repository, you can now create your own implementations as you're not restricted to using the old workflow code.
Getting Started with the Order Repository
In the new version of commerce, we now have an order repository for managing orders, which implements an IOrderRepository. In your order repository, you can do standard things like creating a new cart, run a promotion etc...
You use the order repository to create a new cart. You then need to type the cart as an IOrderGroup. Using this approach means you can create your own implementation of cart by implementing IOrderGroup and pass that into the repository :) In IOrderGroup you can then set and get features like address, currency, forms, promotions etc...
Getting the total for the basket
Checking Inventory Exists
If you need to check if an item exists in stock you can use the warehouse inventory service:
Enabling Beta Functionality
At the time of writing this, the new order repository and promotions engine are in beta mode. In EPiServer beta functions are not available out of the box. TO enable beta functionality please read: How To Enable Beta Features In Episerver
NOTE: THIS POST WAS WRITTEN WHEN PROMOTIONS WAS IN BETA. THE CODE CHANGED SLIGHTLY WHEN IT WAS RELEASED INTO PRODUCTION
The other new feature from the new promotions release, is the IPromotion engine. The IPromotionEngine is the new way to apply discounts to your cart. Gone are the days of old workflow projects and in with a nice new interface friendly repository engine.
In my previous post 'The New Order Repository In Commerce' I went through some of the benefits of using the new order repository that comes with Episerver commerce 8.12.0.
Creating our promotion
The first thing we do is create a class that inherits from EntryPromotion. EntryPromotion inherits from IContent so you can define your promotion the same way you do a block or page. The promotions engine will not pick up the promotion unless it has a processor. To create a processor we inherit from PromotionProcessorBase passing in the custom EntryPromotion we defined above. The processor is the thing that will be called when the promotion engines run method is called. In here you will need to add your logic to determine if the line items match the rules for your discount.
The last part of the puzzle is to create a result. The actual logic of what discount should be applied to the basket.
Now in our code when we come to add a new line item or when we checkout, we can run the promotions against the basket. This can be done by using the IPromotionEngine and passing in an IOrderGroup.
Clearing The Basket
When you start creating custom promotions you will very likely need to clear your basket out. When I tried implementing this I found a lot of issues being thrown from the promotions engine run method for having more than one content reference for a promotion in my discounted list. If you do not know how to clear your basket, log into the Episerver commerce manager, click the commerce manager tab and select order management. From here you should be able to find your basket and delete as required:
After trying to implement this in beta it definitely wasn't as straight forward as I had hoped, especially with the lack of documentation (only to be expected for a beta feature). When you get everything up and running, adding promotions in this way is a lot simpler and the code is a lot more obvious what it is doing. If I had the option I would avoid using the old commerce workflows as much as possible and use this approach.
I've blogged previously about Adding a custom field into the commerce customer object via code. After a recent upgrade to commerce, our DataContext.Current.MetaClasses always returned null in our Initialization module until the commerce migration script was run. A good example why you might want to use this is on your test server deployment.
When you use a continuous integration process to deploy to a server, instead of using a central database server, you could delete and re-build the database on each deployment. You can then use fixtures to pre-populate your Episerver website with pages and blocks automatically. As part of this process, we want to include a test customer to be able to log-in.
If your customer also has custom properties then you need to make sure they are run when the application launches. If you have had a similar requirement to pre-populate your objects before the migration script is run can be done. it's just not documented anywhere! Luckily, within CustomerContext.Current.GetContactById() there's a check to see if the customer object has been created yet if not, it will run a command to update database script to create the Customer MetaData class
In today's guide, we're going to cover how to get products and variants from Episerver commerce to use on your website.
Getting A Product/Variant Using The Code
If you want to simply get a reference to a product and you know the catalogue or product code, then you can use the ReferenceConverter.
Getting A Product/Variant Using The Id
If you want to simply get a reference to a product and you only know the Id, you can also do that. Note: You will also need to provide the workId/version Id.
Getting the entry Id from a content link
In today's guide, we've covered the different ways of retrieving products or variants from Episerver commerce via the API. All products and variants have a unique code, sometimes known as an SKU, that is associated with it. If you know this you can find a product via the code. Like Episerver CMS you can also use the Id to look up a product. In these instances, you will also need to add the version/work id for the content you want. By default, if you use this it should work in the majority of situations.
In today's guide, we will talk about the Episerver Commerce API, specifically, surrounding parent items. If you need to get the product or the node that a variant is associated with then this is for you. In this example, I'll be using this catalog structure:
With the following product and variant:
When we work with Episerver CMS we are used to getting the parent page using ParentLink. In Episerver commerce we work with NodeContent, ProductContent and VariationContent. All of the types inherit from IContent and each type contains a number of properties that you would expect to find in a CMS page. If you use reflector you should be able to see one familiar property, ParentLink, defined in 'CatalogContentBase'. Each type works slightly differently BUT they all have ParentLink properties. If you use the CMS frequently, ParentLink may work differently than you expect.
In the dummy catalogue structure defined above, we have a node, with a product that has a child/related variant. On the variant, if you called its ParentLink method I think it's a fair to expect that you would get back a reference to the product, but you won't. Instead, you will get a reference to the NodeContent that the variant belongs in, e.g. it's parent. In Episerver Commerce the ParentLink will return the parent folder the product or variant lives in rather than the variants parent product.
To reiterate, ParentLink does not relate to the product/variant hierarchy, it relates to the folder/node structure. There are many situations where you need to know this information so it's a useful API call to know about BUT it does work differently than how the CMS behaves. Carry on reading to find out why...
Instead of using ParentLink, the recommended way of getting the catalogue nodes/categories that a product or variant is related is via the GetNodeRelations method on the product/variant. Calling GetNodeRelations will return the catalogue node the product belongs to within the catalogue tree.
When we get a variant the parent/child relationship might not be known. A variant might be associated to one or more products. The problem with a single property like 'ParentLink' is that a variant can potentially have many parents.
In a lot of projects, this variant to multiple product relationships won't be needed and a variant will only be related to one product. In these circumstances, the easiest way of getting a product where all variant can only have one parent product can be seen below:
On VariationContent you should be able to find the 'GetParentProducts' method. This method will return all the products associated with your variant. If you are confident you have a one-to-one product/variant relationship in your catalogue, you can simply use FirstOrDefault() on the variant to get its parent product.
If you are struggling with GetParentProducts, your next stop is to try and use ParentEnties. If you have a variant and you want to know about the products that it is related to, you can use the ParentEntries property in EntryContentBase.
If you have more complicated requirements than the API calls above, you can always search commerce directly yourself using a CatalogEntrySearchCriteria. Using CatalogEntrySearchCriteria you can search the commerce catalog against properties like:
CatalogNames, CatalogNodes, ClassTypes, Currency, EndDate, FuzzyMinSimilarity, Locale, MarketId, Outlines, RecordsToRetrieve, StartDate.
A snippet of code that will search for a product with a given name would look like this
In today's guide, we've covered the differences in the catalogue hierarchy compared to a normal CMS hierarchy. In commerce, we deal with NodeContent, ProductContent and VariationContent. The relationships between these types is a lot more complex than a standard CMS page structure and objects like variants can have multiple parents.
In Episerver Commerce, we have two types of API calls when dealing with products/variants. One to get the folder/node structure a product/variant might live in and the other one being the product/variant relationship. We've covered ParentLink which can be used to find the parent node an item lives in. We've also covered GetParentProducts() to get a variants parent. If that fails you could also try to use ParentEntries.
If your requirements are more complex than a simple parent mapping and you need to use your own filtering, then you should look into using SearchManager and CatalogEntrySearchCriteria.
In previous articles, I've talked about Using The New Promotions Engine in Episerver Commerce and The New Order Repository In Commerce.
Do not forget you need to read this as well How To Enable Beta Features In Episerver. That covers a lot of the basics but it fails to cover how a content editor can create a campaign and discount within Episerver.
Open Commerce Manager
Select the marketing tab
Create a new campaign
Click on the plus button on the top left-hand corner of the page and add a campaign name.
At this stage, you will have to fill in the appropriate campaign details. I won't cover this bit but it is worth noting that if you want extra campaign details you might want to create a custom campaign. You can do this by creating a class that extends the default SalesCampaign type. An example snippet to create a custom campaign can be seen below:
Creating a Discount
After we have created a campaign, click the top left plus again and click discount.
From here you will need to pick out of all the discount types you have created in your solution via code.
These discounts work exactly like a page or a block so the properties you will need to fill in for your promotion will be based on the properties you defined on your discount.
Activating The Campaign and promotion
One important tip that can lead to a source of frustration is to forget to enable the active checkbox on the campaign AND all the discounts within them. If you do not activate the promotion it will not be triggered when the promotion engine is run.
After you have created your campaign and discount and you have the code to apply the discounts (see below) you should have everything set-up. You will want to add this code in the add line item and update line item areas in your basket code.
When you run this code you should be able to hit a breakpoint in your promotions processors evaluate method. If the breakpoint never gets hit then make sure the campaign and promotion are active AND they have a valid start and end dates.
In today's guide, we've walked through how to create a campaign and a promotion within the Episerver commerce manager. The process is very simple but there are a few hidden gotcha's you should be aware of.
When you start working with Episerver commerce, you might become overwhelmed with the number of API's available to you. Finding the right API to do the task at hand can be a frustrating and time-consuming exercise at times. The Episerver SDK does hold a lot of information but it can be a bit patchy and vague at times.
I've definitely lost my patience a few times trying to figure out how to do some simple task. The aim of today's guide is to try and explain some of the API's available to you for working with items that live within your PIM (Product Information Management) / Commerce Catalog.
When you work on an e-commerce project with Episerver commerce, you will need to work with the items within your PIM a lot. These will include the standard things like creating a folder to add a product, getting data to display a product on your website, getting an item to add to a basket or even associate a product with a designated category.
In Episerver terminology, the items you will be working with are VariationContent, ProductContent, BundleContent, PackageContent and NodeContent. More information about these types can be found here.
VariationContent and ProductContent are your products and NodeContent are folders you can create in your catalogue. I'll ignore the other types for this article but it can be handy to know they exist.
IContentRepository or IContentLoader
If you have worked with the Episerver CMS before, it is very likely that you will be familiar with the IContentRepository API. The Content Repository is the API you need to use to get the data about your products and variants from Episerver.
The content repository is pretty easy to work with, with the standard Load and Save methods. I've talked about the IContentRepository before quite a lot and if you want to see some code examples of how it works, I suggest you have a look at these posts How To Load And Retrieve A Variant or Product From Episerver Commerce and How To Get a Catalogue in Episerver Commerce
If you are confused about the difference between IContentRepository or IContentLoader, IContentLoader is a read-only version. IContentRepository allows you to do things like Delete and Save. Behind the scenes, IContentRepository will call IContentLoader, and performance-wise, there isn't really a massive hit between the two. Due to this, I generally tend to favour using IContentRepository because as your code base grows, if you suddenly decide you need IContentRepository you may have to refactor a number of unit tests when you could have just used IContentRepository in the first place.
The reference converter is a very simple API but is very useful when working with Episerver commerce. In a lot of circumstances, you may only have your products SKI (Stock Control Identifier), or, in Episerver terminology, the products 'Code'. The reference converter takes in this string value and returns you a reference to the matching Episerver object. Remember all codes need to be unique within the catalogue.
The reference converter talks to the database directly and does not work with a cache. For this reason, it is important to get the architecture for your website correct so you do not have to repeatedly make unneeded database calls when you're rendering pages.
Up until how we've been dealing with API's at a very high level of abstractions of the nice classes we've designed for the system. The CatalogContext takes us down a notch and works on the DataTable and generic DTO level catalogue; for example at this level, instead of working with an actual product we have defined in the code, we work with a generic CatalogEntryDto. Working at this level, you get access to a few things the IContentRepository doesn't provide. I
t also allows you to work more with the relationships and associations between the objects. The CatalogContext is similar to the Episerver Data Provider whereas they both make use of the singleton pattern. The downside of this approach is that it makes it very hard to unit test your code. This is why if you have access to the newer versions of commerce I would always recommend working with IContentRepository and the ILinksRepository/ The code to get a product can be seen below:
To get a node:
The links repository is one of the newer Episerver Commerce API's, available from version 7.5 onwards. The links repository is the place to look for handling catalogue relations and associations; for example, if you want to change the parent of a node, or, add an association (link) from a variant to a catalogue this is the API for you. As the repository works via an interface it's all unit testable which is nice.
In today's guide, we've introduced and hopefully explained the API's you will need to use when dealing with objects within the Episerver commerce catalogue. There is a number of older and new API's available to you, depending on which version of Episerver commerce you will be working with. If possible, use the newer API's that use the ServiceLocator. Using these API's will allow you to unit test your code. Here are some basic dos and don'ts:
- Use IContentRepository when you want to access your product data
- Use ILinksRepositorywhen you want to play with the associations of objects within your catalogue
- Use CatalogContext when you want to work with a lower level of abstraction within your catalogue
- Use ReferenceConverter to get an Episerver reference based on a product code
This is another short and simple How To guide. In the latest version of Episerver commerce, we have a new interface available to us called the IOrderRepository, we get access to the order repository the standard way by using a Service Locator or the Injected property (read Dependency Injection In Episerver - ServiceLocator and Injected Explained for more information).
After you have access to the cart, you need to decide which form you need to use. From my experience, most people use a single default Form to store a users line items, which is what we are going to do in the snippet below. When we have the form we can then add the line item. Shipments can be used to allow the same order to be split and shipped to different locations. In my experience, I've never had a requirement to use this, so again we use a single shipment architecture.
Adding A Line Item - Episerver Commerce 7 below
The classic way of getting access to the cart is via the OrderContext. This method is not very unit testing friendly so if you can upgrade to the latest version of commerce, it is worth the effort. If you cannot upgrade then this code snippet is the way to go:
Lastly, there is also a helper method that can make life a bit easier. The cart helper is an Episerver helper class that provides a set of standard features for the management of carts and orders. Cart helper doesn't use IOrderRepository (at time of writing). Using it means you have less duplication in your code base but you do lose some flexibility in regards to the options you can use.
That covers how to add a line item into the basket. The code isn't very difficult to grasp. With the new IOrderRepository unit testing your code is easier. If you can't use the latest version of commerce then OrderContext is still available.
When we work with the basket in commerce, storing multiple custom objects against a line item can be tricky. We can extend line item to have as many custom single properties as you require, but we do not have the option to create new arrays or lists against a line item. In today's tutorial I am going to discuss how to get around this limitation.
I have previously written about how to extend the LineItem class in this article Adding Custom MetaData to the LineItem Class in Episerver Commerce via Code and Adding Custom MetaData to the Cart Class in Episerver Commerce via Code
The first thing you will need to do is create a custom property against the LineItem class or the class. Where you store your custom objects is up to you and will probably be dictated by your requirements. In this tutorial I'm going to assume you've done that bit and we'll be working with a custom property already set-up on the Cart, so I'll skip the code.
A very quick and easy win to serialise data is to use Json.Net. Json.Net provides the methods where you basically define the.NET object type you want to convert and the API does the rest for you... it really is that simple. More information about the Json.Net serialisation and deserialization can be found here. For this little demo, we will use a custom object I've randomly created, which looks like this:
The first part of this process is storing your custom .NET objects in the cart. In the method above, we pass in the cart and the objects we want to work with, use JsonConvert to serialise it and then access a customer property on Cart (I'm assuming you have already set this up using the links above) and storing it.
The cart needs to be saved. I'm currently using the new commerce Order Repository to load and save my cart but as it is still in beta, the majority of readers won't be using it. This is the only reason why I have omitted the save code from this snippet BUT you will need to save it if you want it persisted to the database.
Next up is getting the data from the cart when you need it. We will still need the Episerver cart. The first thing we do is get the serialised data we stored in SerializeVouchersToCart, we then user JsonConvert.DeserializeObject to get the objects back out of the cart.
Today's tutorial was quite basic but very useful if you need to work with custom objects and your Episerver Cart or line item. Instead of being stuck with single properties, we can use Json.Net to serialise/deserialize objects. This allows us to store lists of objects which can be extremely useful. One word of caution though, you need to consider how many objects you will be storing. As you'll be serialising objects in a single field, there will be a maximum amount of data you can store.
I have previously written about how to extend the LineItem class in this article Adding Custom MetaData to the LineItem Class in Episerver Commerce via Code I had a question recently about how to do the same thing for the Cart.
The code to add a custom property is very similar as adding a property to the Lineitem class, the only difference being the class you get from OrderContext.Current. When working with Line items we use OrderContext.Current.PurchaseOrderMetaClass and when we work with the cart we OrderContext.Current.ShoppingCartMetaClass.
This is exactly the same as if you want to extend Order Form, Order Address, Order Item or Payment Plan. use the same code snippet as below, but swap the use the typeReference with the class that you want to extend. You can then use the classes CreateField method to add your custom property. The cart code will look like this:
You can then access your property using the following code:
Today, we've talked about how to modify the code to add a custom property to the lineItem class to now work on the cart class. The process for all the commerce objects is all very similar, you useOrderContext.Current to find the class that you want to modify, define a custom MetaField then use the AddField method to store it to the database.
When you are working with content within the PIM, you may want to create multiple associations from the products and variants to different types of node. Before we get into the code, I should probably mention that an association in Episerver commerce is different to the normal Episerver CMS navigation hierarchy structure.
In the CMS for example, a page can only have one parent. In Episerver Commerce things work slightly differently. A product or variant can be associated under multiple nodes. This is really useful when you have requirements like, creating a central store for all your products and then having a discounted node section to apply discounts to products.
Another potential example could be on multi-region sites where a product may need to live under several country nodes to be applicable to be sold within that market. As Episerver Commerce works slightly differently than CMS, it also means that the API call is slightly different than the standard CMS approach. In Episerver Commerce when we want to create one of these associations we use the ILinksRepository within the EPiServer.Commerce.Catalog.Linking namespace.
In the snippet above, we created a Node relation that contains a link to the source (the game or variant) and the target (the node we want to associate the product or variant too). Even though it is called UpdateRelation, it's the method you want to use to create a new association. Simply add your node relation and it's as simple as that. In your catalog you should now see the variant added as a relation:
WORD OF CAUTION
When you add the code, the Target must always be a Node. You cannot create a node relation between two variants, or, products for example. If you try to set the variant as the target you will get the error below.
In today's tutorial, you have learnt the difference in the navigation trees between Episerver Commerce and Episerver CMS. In Episerver CMS we use a very classic page navigation structure where each item can only have one parent. Episerver commerce works slightly differently. Catalog items can have associations to multiple parents.
When we want to create an association in code we can use the ILinksRepository. To create a new association we need to use the 'UpdateRelation' property, simply add the child item into the source and the parent into the target and you should be all sorted.
Trying to create, update and save objects in commerce can cause quite a lot of confusion. The confusion I generally see around the usage of Episerver commerce API is people using the wrong one and then wondering why it didn't work. In today's guide, I'm going to walk through the different API's that are available to us as developers.
Why So Many API's?
Episerver commerce has three different API's for dealing with different areas in commerce. We have:
- The Catalog
- Built in Episerver Objects
- Custom Objects
If you look in Commerce Manager in the Administration section, you see these two folders:
This is a good visual example of the different areas the API's focus split. When adding items into the catalog, the process works like the CMS as it uses a typed content model. You create your own class and inherit from a commerce catalog type, you use the [CatalogContentType] attribute to decorate the class with the standard things like Name, Description, and GUID and then you implement the properties you want within the class itself.
You can then use the normal CMS APIs, IContentRepository or IContectLocator to query those objects. If you want some more information about the catalog then have a read now, The Different Ways Of Getting Items From The Catalog in Episerver Commerce. The new from commerce 7.5 up typed content model is based upon the older is Metadata Plus.
Built-in Episerver Objects
Meta Data Plus is the original API for accessing a lot of commerce content. From Episerver Commerce 7.5 forwards, I would not recommend using Meta Data Plus for doing tasks such as adding and retrieving catalog items, as mentioned above use the typed content model approach instead. It's useful to know about Meta Data Plus (and Business Foundation, which we'll get to shortly) when you want to extend the out-of-the-box catalog/order metaclasses.
Meta Data Plus allows the additional and extension of objects, or, as known in commerce 'Meta Class' by adding on extra properties, called 'Meta Fields'. So for example, to load a class from the database we would use code like this:
In this example, metaClassName would represent a table that existed in the Episerver commerce database. In this example 'Contact' is an Episerver out-the-box thing, that lives in the [cls_Contact] database table. The classes you can access via Meta Data Plus, include Contact, ContactNote, Address and Organization. In reality, you probably won't touch this area of code too often... you will, however, be a lot more likely to work with the newer Business Foundation Objects.
Business Foundation Objects
If you want to work with your own objects with-in Episerver commerce, Business Foundation objects are your friends. Business Foundation Framework came slightly after Meta Data Plus but again is another API the works with objects within Episerver commerce. Business Foundation objects allow you to create new 'Meta Classes', which you can add fields to, with different data types.
Like Meta Data Plus when you create a new class it will actually create a corresponding database entry in the commerce database. Any data you store will then be saved within this table. Business Foundation Objects and the Meta Data Plus are very similar and I personally think it's a bit confusing when you're trying to figure out what API you need to use to do a task.. but moaning about it won't get us anywhere. The snippet below shows you how to query a business object called, Contact and then adds a custom property to it called "MiddleName".
To access your business foundation objects, you can use the following MetaModel instance, to get access to all the business foundation objects in the system. This can be done using the following snippet:
A Word Of Caution
On one of my recent projects, one of the developers got quite confused between the two APIs. If you use Business Foundation Objects API you can run into cross-compatibility issues, for example, in the diagram below:
There are two different MetaClass tables, if you use a Meta Data Plus object its definition will be created in one table if you use business foundation objects your class definition will be created in the other.
In the [MetaClass] table things like OrderForm, LineItem, and all your custom catalog definitions live. Items like Contact, Organization, and Address live in the [mcmd_MetaClass] table. If you find yourself scratching your head why you can't access your data or you can't save an item correctly. The first thing you should do is to make sure you are using the correct API to connect to it.
I've talked previously about Adding a custom field into the commerce customer object via code, Adding Custom MetaData to the LineItem Class in Episerver Commerce via Code and Adding Custom MetaData to the Cart Class in Episerver Commerce via Code.
In today's post, I'm going to talk about doing the same for the Purchase Order class. After a customer has placed an order, you will need to use the Purchase Order class to save information about the order for invoicing, reports etc..
In order to to add a new meta field, we need to use the MetaDataPlus API. First, we need to check the field doesn't already exist. If it does, the AddField method will throw an exception. This is done using OrderContext.Current.PurchaseOrderMetaClass. As the name suggests, this gives us access to the in-built PurchaseOrderMetaClass metadata class.
After we know the field doesn't already exist we can then create it. This is done by creating a meta field, then using the OrderContext.MetaDataContext in order to save it. First we use MetaField.Create passing in the parameters we care about, then the result of that is passed into OrderContext.MetaDataContext.AddField() and the rest is done. You should know using this approach, each field you add needs to be unique. Even if you tried to add ProductName on the Line Item object, for example, Episerver will throw.
In today's post we've talked about how to create custom fields in the Purchase Order class. This is done using the Metadata Plus API.
When we work with Episerver and Episerver commerce, all the data we work with is stored within two back-end databases. When we build projects, you should never write any form of code that talks to the database directly. Everything should always go via the Episerver API.
If you don't, you can corrupt your installation and completely kill your website. There are certain times when you come across one of those annoying bugs that don't seem to make any sense that taking a peak in the database to check that the data you expect to see is there in the correct format.
In today's tutorial, I'm going to cover some of the most useful tables that I've needed to use over the years. The point of this article is to grow and expand over time, so if you want any knowledge about the Episerver database, please leave a comment or email me.
The Tables Explained
This is the table that stores your PIM / product catalogs. This is the top level item for your product catalog and contains things like default currency and default language.
This table stores your Episerver commerce admin/editor user details. Look in here to check which accounts exists in the system, the email address specified, the user id. This can be handy when you have to implement your own custom membership provider.
This is the table that's used to store any additional meta fields that you create the line item class. Each custom meta field that you add will be displayed in an appropriate column.
This is the table that's used to store the items specific to the IOrderGroup. In here you will find data like your carts subtotal, currency, market id and total.
This is where the purchase order information will be stored. If you add any custom fields to the Purchase order, these will also be created within here.
This is the table that stores the data against the Episerver cart. Any custom fields you add to the cart will be displayed in a column in this table.
This table lists the available payment providers that are available within your project. The IsActive property is useful if you need to switch a payment gateway on or off.
This is the table that's used to store any promotions that are applicable to the cart. In your promotions processor, you return a 'PromotionsInformation' object. Data that's stored in here includes the promotions ContentReference, the SavedAmoun, the Description and the IsActive state.
In today's guide, I'm going to cover the build in Episerver purchase order object. For those new to commerce, the purchase order is the object where you save all the information about the order at the place of purchase. After the user has paid, all the information about the order needs to be stored in a format that won't change.
I worked on a recent commerce project where the solution used a third party order system to place orders. In this scenario, the developer in question was still using the cart and the line items to populate the order document. I find this architecture approach very flawed. If the cart or the line items change from the time the system gets the payment provider authorization/capture to the moment in this scenario the order system was called, then in the worst case scenario the user might get charged x amount and the confirmation page and email etc.. that was implemented to use the cart and line-items.
If you are implementing a new commerce project then I would strongly recommend that, on the moment the payment has been captured, you save everything you need in the purchase order and clear the cart. Doing this forces any developers to use the correct object rather than using the wrong objects and risk introducing bugs that might make the user see out of date. If the purchase order object does not have the fields you need, you can either add them in manually via commerce. Personally, I don't like this approach. Instead, I like to add new fields in code.
This way I can guarantee that no typos happen and I can clean my database and rebuild the database easily. If you need some more information about how to do this then I would recommend reading, How To Add A Custom Property To The Purchase Order in Episerver Commerce.
How To Get A Purchae Order From Episerver
To get a purchase order from Episerver is pretty simple:
In this code we use the PurchaseOrder helper in the Mediachase.Commerce, Mediachase.Commerce.Orders namespace. In here you can pass in the cart or order group provider Id. The PurchaseOrder allows you to do the usual suspects of operations like UpdateShipmentLineItemQuantity, Search, RemoveLineItemFromShipment etc..
There is also an alternative way to get Purchase Order information from commerce. I definitely wouldn't recommend using this approach, as it requires a lot more code and will likely break in future versions, however, it may come in useful I guess?
The code above uses a pretty old school hacky way. You create some OrderSearchOptions and OrderSearchParameters. Manually define some SQL in code (yuk!) and they pass the objects into the OrderContext.Current.FindPurchaseOrders() method to get the purchase order. Again, I would not advise you to use this but if you come across this in an old project when you upgrade, remember there are a lot easier ways to get purchase order information.
Creating A Purchase Order
To create a new purchase order within Episerver is also pretty simple in the latest versions of commerce. The easiest option is to use the 'IOrderRepository'
In today's guide, I've talked about the in-built purchase order object. In Episerver commerce, this is the object you need to talk to when you're working with after sales data. My advice would be to store all the information you care about in the purchase order and clear the current users cart as soon as they purchase to prevent random bugs being introduced into your code base. You can do the standard CRUD type of operations using the PurchaseOrder API and should be your first port of call when you want to work with purchase order objects,
There are certain circumstances when working with Episerver or Episerver commerce when you need to come off the beaten track and interact with the HTTP context a bit more closely. For example, if you need to create a custom ActionFilterAttribute, or, you need to to do some routing wizardry with communication between blocks on your product pages.
One of my most popular tutorials EPiServer 7 : How do I get the “CurrentPage” from a controller ? deals with a similar principle. The code below assumes that you are working with-in an ActionFilterAttribute but as long as you have access to the controller context the same principles apply to wherever.
Getting EntryContentBase from the HTTP context
The first approach is the generic approach that will get you access to your product code. This involves getting the currentContent out of the RouteData and typing it to an EntryContentBase. Using this code will allow you to process products and variants at the same time.
Getting the Variant from the HTTP context
If you want your code to be more specific to the data you are working on, then you simply type it to the default Episerver objects VariationContentor ProductContent. In most scenarios, you will be working with your own commerce types as you would usually
In today's tutorial, we've covered how to commerce products and variations directly out of the HTTP context/controller context. We use the currentContent key in the RouteData table and then type it to the object you care about. The code is pretty simple and straightforward but can be a bit tricky at times to figure out yourself.
You might not have come across the term 'trust signal' before but you will have seen it used countless times on most major e-commerce websites. A trust signal is an area or feature on your website that helps builds trust with your website visitors. If people visiting your website don't trust your brand, your product, or have concerns about what you will do with their personal data, then they won't buy anything from you.
There are many different types of trust signals you can integrate within your website. Different trust signals can be leveraged to help encourage your website visitors to interact with your business, or make a transaction. A lot of research has been made into which trust signals are more likely to help convert. Implementing the correct trust signals into your sales funnel can instantly double conversion rates. In Building Trust on Ecommerce Home Pages, 70% of website users won't follow through with an online purchase if they don't trust the source, so using the right trust signal is key to good conversations, so it's easy to see where these stats come from.
Digital trust has become an important topic for any successful web platform and it shouldn't be ignored. When someone visits your website, a strong virtual handshake is the best way to encourage someone to make a transaction with you. In today's guide, I'm going to cover some of the most proven trust signals to help enable site conversions and revenue growth.
The 5 Most Effective Trust Signals
Being able to find unbiased fellow consumer reviews is an extremely powerful influencing factor to help consumers decide to purchase one of your products. I would be extremely surprised if anyone reading this article hasn't used reviews to base their decisions about downloading or purchasing something. Common examples of reviews include:
- IMDB's reviews when deciding which box-set they should start on next
- Amazons reviews to help you decide which book or electronic goods to buy
- TripAdvisors database to decide, what tourist attractions or hotels you want to stay in
In How Social Media is Changing the SEO Industry the study showed 88% of consumers will check out reviews before making a final decision on a purchase. If you add a user review section into your Episerver commerce website where your visitors can read other customer reviews of your products, and review products themselves, then your conversations will increase.
Demonstrate Social Proof
Social proof is another powerful way to build trust with your customer base. In Consumer Trust in Online, Social and Mobile advertising grows, Jacob Neilson found 92% of consumers trust recommendations from friends and family above any other type of advertising. Using social proof will allow you to build trust with your visitors.
If you can prove that other people visit your website and think it's cool you are a lot more likely to build trust with them. Research has shown that social profiles work well when it's positioned on every page of your website, either in the header or footer. Having your social proof in the same spot makes it super simple for the user to engage with your brand and builds trust with your customers. In your Episerver website, add some social icons to help build trust.
Having reviews and social proof is a great way to build trust with your visitors, but nothing builds trust quicker than a customer being able to call you up and talk to you directly. A recent client of mine understood this principle so well that the sales funnel on their website was solely built to get people interested in their products to phone up and speak to one of their phone operators. T
he company in question knew that the best way for them to build relationships was through communication. For their trust symbol, they had the operators name and photo that they would speak to for each product, along with their telephone number. The call to action for a customer to phone up an operator was constantly visible on the website, no matter where on the site a visitor happened to be. Contact information should be available from every page, either against a product, in the header or the footer. Contact information you should include on your site, include:
- Email address
- Phone number
- Reveal Your Geographic Location/li>
- Opening hours
- Show Your Face, or your teams
Displaying contact information and inviting people to get in contact with you before they make a purchase proves that you've got nothing to hide. The first time someone stumbles across your website their trust will be at it's lowest. If you can get someone to phone you up, or email you, then the chance of making a sale with them exponentially increases.
Third-party badges and certifications
UXMatters performed a study about the importance and influence of third-party badges. They found icons like 'Visa' and 'Paypal' are the most trusted elements on a website for first-time. Just having a list of images of payment types you support in the checkout process is a simple way to build trust. When you want to try and prise a visitor from their money, they need to feel safe and secure with your platforms. Shopping cart abandonment can result in 67.45% of lost sales according to Shopify.
The main reasons for shopping cart abandonment include unexpected costs, website crashes, performance and lastly concerns of payment security. Being able to build any extra trust with your customers in the checkout process stops losing people in the funnel and could result in a large reduction in loss of sales. In Episerver this is a simple as providing an image property on your checkout page template, to allow content editors to upload third-party trust icons.
Multiple payment methods
Recently, I wanted to buy some gig tickets for a band playing in London, the gig was for a small up and coming band playing in a small grotty venue in Camden. The venue's website looked like it was built by a child and the only way to purchase an item was through a Paypal button. Just from the poor design and limited payment options I instinctively found a more trustworthy site to buy the tickets and the venue lost the commission of the sale.
I'm sure everyone reading this can relate to these dodgy looking websites that failed to build your trust so you found an alternative way to purchase something. When you deal with online sales, customers can live all over the world and will want to pay for goods in a variety of ways. Customers in China will want to pay in a different format than customers in the UK. Luckily, Episerver Commerce has several payment gateways already pre-built that you can integrate into your project.
The greater the variety of payment methods you provide the less likely you will lose sales. The wider and more choice of payment methods you accept on your site, the more trust you will build with your visitors. With the likes of DataCash, DIBS, Klarna and PayPal Episerver has gone to a lot of leg work in order to help you leverage your own social proof.
Building trust is a key aspect of creating a successful Episerver commerce website that will convert leads into sales. In the online world, one of your main targets should be in promoting the trust-building journey with your users. You need to identify what signals your customers need to ensure they follow through in your sales funnel.
From a lot of reading around on the subject, this article presents the most necessary and compelling techniques for building trust in your digital marketplace. Key takeaways from this post should be to build a website where visitors trust that the products you sell are legitimate and that they can entrust you with their data and money.
Creating and planning your first e-commerce project can be a daunting thought. E-commerce websites are complex and in general, an e-commerce website will have a lot more moving parts and things to consider compared to a standard website. The primary focus of this post is for beginners completely new to e-commerce with the aim to educate them about the basics of e-commerce and what you will need to consider for your project. This guide isn't going to cover any code but explains what e-commerce websites are and why you should consider Episerver commerce.
What Is ECommerce?
Wikipedia defines e-commerce as:
Electronic commerce, commonly known as E-commerce, is trading in products or services using computer networks, such as the Internet. Electronic commerce draws on technologies such as mobile commerce, electronic funds transfer, supply chain management, Internet marketing, online transaction processing, electronic data interchange (EDI), inventory management systems, and automated data collection systems.
Modern electronic commerce typically uses the World Wide Web for at least one part of the transaction's life cycle, although it may also use other technologies such as e-mail, mobile devices, social media, and telephones.
Having a store on your website will provide you with a great potential revenue stream and choosing the right platform is a key factor. Episerver CMS is known for its ease of use even for non-programmers, and this is also the case with Episerver commerce.
E-Commerce Website Considerations
Let’s say you've decided to start an online store, the next decision is will we buy an established e-commerce platform, or will we develop a custom one in-house? Developing in-house will allow you to create something that will exactly meet your business needs, however, if you're reading this then you are probably new to e-commerce and you'll have to go through a lot of learning and pain in order to get to that stage.
In fact, whenever I've done these types of the project in-house, it's always taken years to get to a stage where the business can relaunch! On the other side of the coin, you have the choice of buying something that already exists. Using an existing project, usually, means you can bolt in a lot of functionality very rapidly. After installing the product (which takes an hour), your content editors will instantly have access to a PIM, customer management, and invoice management screens.
Your developers will also have access to a range of API'S to talk to, add items to a basket, checkout and send an order to a payment gateway. Obviously, the above statement is very idealistic and in reality, you will hit problems and issues. It's never just a case of buying some software and it does everything you want it to.
Almost every commerce has them, but the principles are the same. When you buy a commercial tool, you're using something that has been developed by people who probably know more about e-commerce software than you do. Another big consideration is updated. E-commerce sites are always high targets for people wanting to do malicious things to your site.
If you build bespoke software you need to keep track of all the latest vulnerabilities and you are solely responsible for maintaining your code. When you use off-the-shelf products, you will also have the benefit of upgrades. There will be a team of core developers working day in, day out, to improve the product. In most cases, you can update a few changes and within a few hours get great new features and bug fixes without having to do anything yourself!
Considerations When Picking An Ecommerce Platform
I'm going to assume you've decided you want to use a third-party commerce product for your website now. In that case, you have several considerations when you want to pick a solution that is either free or won’t cost you more than a hundred bucks. The potential concerns for you at that time are:
- Customization: How flexible is the platform. Your business will have custom workflows and processes that will need to work in conjunction with your website. Will the new software be easy to customise and make it work the way you need it to?
- Security: Security is the biggest concern for every e‑commerce site. No site can afford the brand damage from fraudulent usage, hacked credit card data going missing. Having bad security not only puts your customers’ credentials at stake but puts you in the firing squad to get sued. How do you tackle such issues?
- Performance: Performance should be a key consideration for any website. You will need a solution that has been proven to work under a high-load.
- User Experience: One often overlooked aspect of building an in-house platform is how long it will take you to write the user interfaces. The PIM, customer management screens will all need to be written. Getting this right will take time.
If you are still reading this, then EpiCommerce might be a good fit for you. EpiCommerce is a paid product developed by Episerver. EpiCommerce has been around in some flavour for nearly a decade so it's been built on a lot of learning. EpiCommerce now powers hundreds of eCommerce websites worldwide, including a number of high-traffic websites. EpiCommerce lets you sell anything you want online with ease.
You can sell a physical, virtual, downloadable, or even an affiliate/external product with this very plugin. Like Episerver CMS, you do not know anything technical to use the product itself, instead of trying to write something custom, you can enjoy a lot of flexibility in selling your products with Commerce. Like EpiserverCMS, commerce is a platform and you will still need developers to do the initial implementation. EpiCommerce is not only about setting up your own web store, EpiCommerce is a complete platform that allows you to manage everything around your online business.
Hopefully, this guide will give you some fuel for thought about your online store. If you want to become an e-merchant and you don't want to write everything from scratch in-house, then EpiCommerce is there to save the day. Episerver is being used successfully by a lot of companies worldwide. If you are considering Episerver commerce, I would strongly recommend you speak to another company who have implemented it.
Episerver Commerce is still an improving product and a lot of improvements have been made to it in the last few years. Episerver is putting a lot of time and effort to constantly improve the product. However, commerce builds are very complex. If you need any help about commerce and want some independent advice, please feel free to ask me anything. You can contact me from this page.
A common requirement on an Episerver Commerce project, is to hook into the commerce pages events handler, for example, you may need to do things like:
- Call an additional search index when a new game/variants is published
- Call a third party service, like a pricing service
- Add custom validation to prevent a product being saved under certain circumstances
In today's guide, we are going to cover the basics of doing this in Episerver Commerce 8, using the CatalogEventListenerBase.
The Catalog Event Listener is new to Episerver Commerce 8. It provides a mechanism to listen to all the vents within your catalog. TO start hooking into events you need to extend from the CatalogEventListenerBase. You can read more about the different event available to you from CatalogEventListenerBase at EpiWorld here.
In order to override the default Episerver CatalogEventListener, you need to implement from CatalogEventListenerBase and then decorate your new class with the ServiceConfiguration attribute with the 'typeof' property set as a CatalogEventListenerBase, like so:
You can then override the events you are interested in like so:
After a few hours working with the API, I probably should warn you that it is definitely not the most developer-friendly API I've worked with. Instead of working with typed objects like you do with pages and blocks in the CMS, the API works on a much lower abstraction level.
When you work with the CatalogEvent entities you will be working in the DataTables and DataRows level. This can make it a bit tricky to figure out what you need to do and where you need to get your data from, but with a bit of persistence you can hopefully survive. After you have your CustomCatalogEventListenerBase set-up, you can now think about events you want to hook into. The rest of this guide will cover a few basic example.
Hooking into commerce's publish event
When you want to hook in the save/publish events, you need to override the EntryUpdating event. This uses the CatalogEntryDto as the source object. The below snippet always ensures the variant code is set to the first value it was published with:
The first thing we do is get the actual data for the content being published, using these lines:
Typing it is really important, otherwise, you won't be able to get any of the VariationContent data that you probably want to manipulate. The next important line in this snippet is this:
You can use RowState check to determine if the data being saved is new, or, if the object already exists in the database.
Hooking into the relation updating event
This event is useful if you want to add validation or similar when you move content around the page tree. When you create new associations, the location of the variant/product can change without the EntryUpdating event being triggered. When we want to hook into the relation updating events we use the RelationUpdating event. This uses CatalogRelationDto as the source object.
In today's guide, we have discussed how you can hook into Episerver commerce's catalog events. Using the CustomCatalogEventListenerBase you can listen out for all the catalogs, nodes, and products events. By overriding CustomCatalogEventListenerBase and creating your own implementation you can override the default event actions and add in your own custom code.
There are several ways you can hook into Episerver commerce events but if you want catalog specific events, then CustomCatalogEventListenerBase is probably your best bet. We also covered two different examples of how you can use CustomCatalogEventListenerBase in your project, one that will prevent a value from changing after it has first been set. The other example shows how you can prevent nodes/products being dragged into certain areas within the Episerver catalog tree.
If you want to import products/variants/catalog nodes into EPiserver commerce then one option that will be of interest to you will be the CatalogImportExport -> Import() method within the Mediachase.Commerce assembly.
A common example of when you may want to do this is when you're working with third-party PIM product like, InRiver, e.g. you want to make changes within your PIM and that process involves an out-the-box-connector that gets pulled into commerce. In this post, I'm hopefully going to cover some of my learnings while attempting to import items into commerce.
Before I go too far into the code, I should point out a perfectly valid way of importing is to get the XML file, parse out the bits you want and then use the normal commerce API to import objects. I think this is still my preferred approach. You probably end up with more code, but, as you're writing all the code yourself, it's easier to unit test and debug when things go wrong.
I'm going to be honest here, getting the import process fully working so things like markets, languages was a pain. If you're pulling in data within an import and you don't have an explicit property mapped in your commerce objects you can inadvertently end up with hidden properties in your products and variants that you can't see in your code.
Getting all the data 100% working, with no import issues can be tricky. One of the big problems being the sheer amount of data you need to keep in sync. I've had to do this on a recent project and figuring out what goes where, where things were stored etc.. required a lot of time and patience. If you're just about to go through this process yourself, then give yourself plenty of time, it'd usually be better to over-estimate than underestimate :)
How Do I Import Code?
The code is, hopefully, fairly straight-forward to understand. I'm reading an export file stored on my local disc, this gets serializing into a file stream and then passed into the Import() method. As long as you have a valid commerce export file this should import correctly.
Import File Overview For InRiver
This section doesn't have anything to do with importing, but it might be handy for me to quickly discuss my learnings surrounding the import file, as no one else seems to have done so.
FIrstly, I should probably say I've only used this importing method once with an InRiver integration, which used the standard connector so I'm not sure how this relates to other types of import files generated for commerce.
InRiver generated a folder, containing an XML file and a zip file that contained all the changes for a given PIM amend. The export folder contains a file called catalog.xml and a ZIP file.
The zip file contains an additional catalog.xml file that contains slightly different data which is also used in the import. When I first tried implementing this, the extra XML file within the ZIP threw me a bit (as I didn't look inside it). For the record it contains data that will be imported, e.g. things like meta-data, drop-down entries etc..
Within InRiver, the names of the properties being imported were contained within the MetaField -> Name. The type can be found within the Type file. If you don't have a matching property on your Episerver product/variant class, when the import runs, any types defined will be imported as effectively hidden fields. If you bump into an issue of missing data within your C# code, you can try the method below to double-check that the property exists.
How Do I Access These Hidden Properties?
If you are new to commerce and you want to know how to access a 'hidden' property, this can be done using this:
As you can see, importing a file into commerce is simple. In most situations, it's the tasks of making sure the right things have imported, making sure meta-data has been added correctly etc... is the hard part. I think I'd still recommend manually writing the code to map your import file, as in the long run, it will be easier to maintain and debug. If your import does dodgy things and all the code is within internal Episerver assemblies, it's harder to figure out exactly what's going on.
In an Episerver e-commerce website, markets are the way you can split up your PIM to different demographics. Obviously, all companies are different and each has its own business process and its own unique sales funnels. This means that the exact criteria that determine a company's markets can potentially be very different between projects.
Some companies might just have a single market, others can define multiple markets, each with its own product catalog, language, currency, and promotions determined by factors such as brand, location, or locale. In this simple guide, I'm going to talk about how to create and query your own markets within Episerver commerce. In this post, I'll hopefully go over all the code you'll need to crack on.
How To Query Existing Markets
In Episerver you can view all the existing markets in your website, via code using the IMarketService API, which you can access via.
How To Get The Current Site Visitors Market
When a site visitor first hits your website, one of the first things you need to do within your request pipeline, is to look-up the market ID they should be using and if it doesn't exist, associate one against them in a cookie or session, otherwise they'll likely just see the default market and won't be able to see the correct products. To get the current market and set the market you can use the ICurrentMarket API :
Get Current Market
Set Current Market
How Do Create Custom Rules When Selecting A Market?
As I mentioned in the introduction, if you need to create multiple markets you will need to write some custom code as your market will be unique to you, e.g. some people might want to store the users current market id in a cookie, some in session. Some might need to query the language to get the market ID, some might need to run some custom code to get a brand name for example.
To do this, you'll need to create a new class that implements ICurrentMarket. All you need to do is write a custom class that implements the ICurrentMarket interface and implements the GetCurrentMarket()and SetCurrentMarket() with their own implements.
NOTE: Don't forget to update your structure map container to use this new class, otherwise it will likely default to the out-of-the-box implementation, e.g. container.For
The code below is based on a requirement I had on a past project. The logic you end up writing will likely be different than this, but, hopefully, it'll give you an idea about it. In this example, on each page request, you'll read the cookie value to set if the market has been previously set, if it hasn't we'll query the current language API to get the culture code. Using the current language code, we can query the current markets to get the matching market.
I Need To Store Custom Data With My Markets, Is This Possible?
Yes, like most things Episerver markets are defined by an interface, IMarket. Out of the box, Episerver gives you the MarketImpl class. You can use this class to define your markets and pass it into the IMarketService to create a new market within your commerce database. If you want to add in your own custom fields, all you need to do is create your own class with your own custom properties, like so:
If you have a need to sell your products to different markets, based on countries, brands, currency etc.. then markets are the place to start. Building markets in Episerver hopefully shouldn't be too painful. All the API's and entities all are interface based, so unit testing isn't too bad.
If you look at the Episerver variant, you will see a MarketFilter property, however, if you look within the Properties collection on the object you'll also see a property associated with the variant called _ExcludedCatalogEntryMarkets. In today's post, I'm going to talk about what they do and when you might use them.
I've only stumbled across the _ExcludedCatalogEntryMarkets property on a recent project. The project in question used inRiver as a PIM with Epicommerce. For those of you unfamiliar with In-River, don't worry too much, InRIver output some XML which is then imported into Episerer commerce using the commerce Import API.
When content is imported, you'll want to define what markets the product should be associated with. The way the import was written in this scenario was that instead of defining the markets it was associated with, it defined the markets it should be removed from.
What made the situation even more confusing, is that _ExcludedCatalogEntryMarkets is a hidden property, e.g. it's not a property that's defined on the variant base class, so if you look in your variant class you won't see it. If you debug a variant though and look in the property collection, it's there.
So my understanding is that if you want to import products using the import API, then you can use this property to define the markets it shouldn't be applied to.
MarketFilter is a property that is defined on the Episerver variants base class EntryContentBase, which you can use to define what markets a variant is associated with. If you're unsure about markets but you have a need to filter the products your customers see based on some criteria, then I suggest you read this for more information how to do that)
The market filter is the inverse of _ExcludedCatalogEntryMarkets. Where _ExcludedCatalogEntryMarkets defines what markets should be removed on an import. Market Filter defines the allowed markets. I'm not too sure why there are two items, but when you debug and see these two properties within the property collection it makes it a bit confusing.
From my experience with commerce markets, the MarketFilter property is assigned from the _ExcludedCatalogEntryMarkets meta field. So if you're having issues with the MarketFilter it may be worth checking _ExcludedCatalogEntryMarkets as well.
Speaking from first-hand experience, having two properties on variants that are similar in nature can be confusing when you're trying to solve a commerce issue. The aim of this guide is to try and help you understand the differences between the two market properties that you might see. MarketFilter and _ExcludedCatalogEntryMarkets do similar things, so it's worth noting the differences between them.
In this tutorial, you will learn the basics of setting up a new payment gateway with Episerver commerce. This tutorial won't go into any specific payment provider details. Each payment provider that I've worked with has been drastically different.
The aim of this guide is to help you get an understanding of the type of tasks that are required. This guide won't show things like code-first for registering a payment provider with Episerver.
Creating A Payment Gateway
You will need to add the code that talks to the payment provider within a custom payment gateway. I suggest that for each provider you need to integrate with, you create a sperate class library.
Within the library, you will need to define a class, similar to this. Within the process method, you can add your logic to talk to your payment provider.
- EpiserverCommerce 7 : Adding a custom field into the commerce customer object via code
- Adding Custom MetaData to the LineItem Class in Episerver Commerce via Code
- Episerver Commerce : How To Add Custom Properties to the Customers Objects in code
- How To Get a Catalogue in Episerver Commerce
- How To Search For Users In Episerver Commerce
- Make The Epi Commerce SiteContext Work From Session Instead Of Cookies
- How to install Episerver Commerce 7 on MVC Site in less than 10 Minutes!
- How To Fix The Episerver Commerce SeoInformation Description MaxLength Issue
- Upgrading To Episerver Commerce 8 : Virtual path to protected packages is invalid: ''.
- The New Order Repository In Commerce
- Using The New Promotions Engine in Episerver Commerce
- How To Intialiase the Episerver Commerce MetaClasses in Code
- How To Load And Retrieve A Variant or Product From Episerver Commerce
- Getting Parent Products and Nodes For a Variant/SKU in Episerver Commerce
- Applying A Promotion To The Marketing Engine In Episerver Commerce
- The Different Ways Of Getting Items From The Catalog in Episerver Commerce
- Adding A LineItem to the Cart In Episerver Commerce
- How To Store Multiple Objects Against A LineItem Or The Cart In Episerver Commerce
- Adding Custom MetaData to the Cart Class in Episerver Commerce via Code
- How To Automatically Create Association Between Objects in the Episerver Commerce Catalog
- The Different Ways Of Saving Content In Episerver Commerce
- How To Add A Custom Property To The Purchase Order in Episerver Commerce
- The Episerver Commerce Database Explained - Hopefully...
- Episerver Commerce The Purchase Order Object Explained
- Episerver Commerce : How do I get the current Product or Variant from a controller or attribute ?
- How To Use Trust Signals With Your Episerver Commerce Website To Double Conversations
- A Gentle Introduction To EpiCommerce
- How To Hook Into Episerver Commerce 8 Catalog Event Handlers
- How To Import Catalog Items Into Episerver Commerce Using The Catalog Import
- Idiots Guide To Episerver Markets
- The Difference Between _ExcludedCatalogEntryMarkets And MarketFilter
- The Basics Of Setting Up A Payment Gateway In Episerver Commerce