In today's tutorial, you will learn how to add a field onto the Episerver commerce customer object... using code alone! This magic will be done using Episerver Commerces MetaClasses. You will learn about two methods to add custom properties to the class via code. One uses the CreateMetaField method found on the customer object itself. The other will use the MetaFieldBuilder class to add a property on the object 🔥🔥🔥.

The reason why I needed to learn how to do this in code, was to allow database changes to be easily and quickly synced across the team and the environments. Whenever a developer pulled code that contained a CMS or commerce schema change, we wanted their local database to be automatically updated. We also wanted to automatically add a test customer in code to make testing easier. In our scenario, the customer had a number of extra properties like NewsletterOptIn. Without using code the team would have had to manually refresh their local databases every few days, which is obviously very inefficient 😔

The customer object is also known as a business foundation object within the Episerver Commerce vernacular. These objects can be accessed using the DataContext.Current.MetaModel API. In 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 access from MetaClasses include RecentReferenceHistory, Customer, Organization, Address, CreditCard, ContactNote, CustomizationItem, CustomizationItemArgument, CustomPage, Folder, FolderElement, ImageFolderElement, PdfFolderElement, CountryExtended. To get a business foundation class you can use several approaches. You can access the business foundation to object itself, like this:

Or like this:

I prefer using the GetMetaClass() approach, as it throws an exception if the class doesn't exist. This makes life a lot easier when trying to debug. Adding the field directly can result in the update failing silently. When this happens, it can be really hard to figure out where the issue occurred. Trust me 😕. The next step is to add the custom field:

After you have a reference to the customer property, you can use its CreateMetaField() method to create the new field (you may also want to check that it doesn't already exist). I would recommend using CreateMetaField but you can also use MetaFieldBuilder. The code below does exactly the same thing:

If you want to deal with multiple business items at the same time, an alternative approach is to iterate through the collection in one go:

Issues

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 note in a forum post that said to add this:

After a bit of trial and error, it seems that we were calling the initialization module before the commerce objects were being created in the database. The commerce migration script also calls the business foundation set-up database scripts (which create these missing commerce objects). If you try getting the business foundation classes before this runs, then they will always be null and you code will fail. Manually generating these scripts will then solve the issues 💥


That's it folks... Happy Coding 🤘