EpiserverCommerce 7 : Adding a custom field into the commerce customer object via code

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:

var customerClass = DataContext.Current.GetMetaClass("Customer");

or

var customerClass = DataContext.Current.MetaModel.MetaClasses["Customer"];

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:

var customerClass = DataContext.Current.GetMetaClass("Customer");
if (customerClass.Fields["Name"] == null)
CreateMetaField(customerClass,
"Name",
"Name",
MetaFieldType.Text);

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:

var customerClass = DataContext.Current.GetMetaClass("Customer");
using (var metaFieldBuilder = new MetaFieldBuilder(customerClass))
{
bool isNullable = false;
int maxLength = 150;
bool isUnqiue = false;
metaFieldBuilder.CreateText("PropertyName", "PropertyFriendlyName", isNullable, maxLength, isUnique);
metaFieldBuilder.SaveChanges();
}

An alternative approach, if you want to deal with multiple business items, is to iterate through the collection:

foreach (var item in DataContext.Current.MetaModel.MetaClasses.Cast<MetaClass>())
{
if (Item(mc => mc.Name == "Customer")
{
if (customer.Fields["MiddleName"] == null)
{
CreateMetaField(customer,
"MiddleName",
"Middle Name",
MetaFieldType.Text);
}
}
}
}
private static void CreateMetaField(MetaClass customer, string name, string friendlyName, string type)
{
customer.CreateMetaField(
name,
friendlyName,
type,
true,
string.Empty,
new AttributeCollection());
}
}

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 forum post that said to add:

var connectionString = ConfigurationManager.ConnectionStrings["EcfSqlConnection"].ConnectionString;
SqlContext.Current = new SqlContext(connectionString);
DataContext.Current = new DataContext(connectionString);

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.

Conclusion

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.

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

More Posts

4 replies

Trackbacks & Pingbacks

  1. […] 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 […]

  2. […] blogged previously about Adding a custom field into the commerce customer object via code. After a recent upgrade to commerce our DataContext.Current.MetaClasses never returned any of the […]

  3. […] 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 is 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 […]

  4. […] 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 is 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 […]

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *