Add a new AddressType value to the mcmd_MetaEnum table

Vote:
 

By default the mcmd_MetaEnum table in Commerce has three values for AddressType: Public, Shipping & Billing:

In my project we want to add some additional Address types. We are looking to do this in an InitializationModule and, at present, have the following code. Is this the best way to go about it?

        public static void CreateEnumField(string name, string enumValue, string friendlyName, string defaultValue = null, bool isNullable = false, bool enumEditable = false)
        {
            var enumType = GetMetaEnumclass(name);
            if(enumType == null)
            {
                return;
            }

            var enumValueExists = enumType.EnumItems.Where(x => x.ToString() == enumValue).Any();
            if(enumValueExists)
            {
                return;
            };

            var metaClass = new MetaClass();
            using (var metaFieldBuilder = new MetaFieldBuilder(metaClass))
            {
                metaFieldBuilder.MetaClass.AccessLevel = AccessLevel.Customization;
                metaFieldBuilder.CreateEnumField(name, friendlyName, enumValue, isNullable, defaultValue, enumEditable);
                metaFieldBuilder.SaveChanges();
            }
        }

        private static MetaFieldType GetMetaEnumclass(string name)
        {
            var registeredEnums = DataContext.Current.MetaModel.GetRegisteredTypes(McDataType.Enum);
            return registeredEnums.Where(x => x.Name == name).FirstOrDefault();
        }
#280466
May 17, 2022 15:35
Vote:
 

I personally don't like using Init modules, personally I like to wrap around the use of Migration Steps. It's something I've presented in the Optimizely Masterclasses I present with Opti

https://world.optimizely.com/blogs/scott-reed/dates/2021/11/run-once-migration-step/ 

This follows the same approach that one of the inbuild IMigrationStep follows and I feel it fits better. But the code approach looks good, all meta fields need to be done programatically now in Commerce 14

#280509
May 18, 2022 7:09
Vote:
 

 you might want to write your code like this

var friendlyNames = MetaEnum.GetFriendlyNames("AddressType");

//check for redundancy, then 
                    MetaEnum.AddItem("AddressType", 1, "Test 1", 1);
                    MetaEnum.AddItem("AddressType", 2, "Test 2", 2);
                    MetaEnum.AddItem("AddressType", 3, "Test 3", 3);

You can put it in an initialization module as you thought. technically you should put it in a IInitializationPlugin but it does not really matter. as long as you have a way to run it, (and fast) I would not worry 

#280523
May 18, 2022 10:25
Scott Reed - May 18, 2022 12:10
Is that better than the migration step approach? I've been teaching this in the co hosted Optimizely master classes so if this is better I can change the approach. I've never used an IInitializationPlugin
Quan Mai - May 18, 2022 13:07
I don't think any approach is clearly better than other in this case. Migration Step is meant to be used by something that is expensive (slow) and meant to run once. this task could be run quick and with a little checking you can run it as many times as you want. Migration Step can be very tricky if you want to re-run it for one reason for another (source: I was responsible for Migration Step :) )
Vote:
 

Thanks for the guidance, it is working now. Full solution below:

// InitializationModule

    [ModuleDependency(typeof(EPiServer.Commerce.Initialization.InitializationModule))]
    internal class AddressTypeInitialization : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            // Create Enum values for AddressType
            DatabaseInitializationHelpers.CreateEnumField("AddressType", "PostAddress");
            DatabaseInitializationHelpers.CreateEnumField("AddressType", "PostOfficeBox");
            DatabaseInitializationHelpers.CreateEnumField("AddressType", "DHLPickup");
        }

        public void Uninitialize(InitializationEngine context)
        {
            //
        }
    }

// Static helper class

    public static class DatabaseInitializationHelpers
    {
        public static void CreateEnumField(string enumName, string enumValue)
        {
            var enumMetaField = DataContext.Current.GetMetaFieldType(enumName);
            var enumFriendlyNames = MetaEnum.GetFriendlyNames(enumMetaField);

            if (enumValue == null)
            {
                return;
            }

            if (enumFriendlyNames.Contains(enumValue))
            {
                return;
            };

            var orderId = IncrementEnumCountByOneToGetOrderId(enumFriendlyNames);
            MetaEnum.AddItem(enumMetaField, enumValue, orderId);
        }

        private static int IncrementEnumCountByOneToGetOrderId(string[] friendlyNames)
        {
            return friendlyNames.Length + 1;
        }
    }
#280530
May 18, 2022 12:50
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.