How can I use one TinyMce config for all multisites?

  • Page Owner: Not Set
  • Last Reviewed: 2020-10-13

I’m using a utility to apply the same Tiny MCE config across all my projects, but I’m getting a ReflectionTypeLoadException exception when it's enumerating all the types.

Specifically I get an inner exception of: Activation error occurred while trying to get instance of type TinyMceConfiguration, key: "".

This seems to have happened immediately following an Episerver upgrade.


Answer

Here’s an example of the base configuration from APTA. The important change is that the assemblies are wrapped in a try catch.

  public static class TinyMceConfigurationUtility
    {
        public static void ApplyDefaultConfiguration(TinyMceConfiguration config, TinyMceSettings settings, params Type[] baseTypes)
        {
            var forMethod = typeof(TinyMceConfiguration).GetMethod("For");

            var types = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(x =>
                {
                    try
                    {
                        return x.GetTypes();
                    }
                    catch (Exception ex)
                    {
                        ex.Log();
                        return Enumerable.Empty<Type>();
                    }
                })
                .Where(contentType => baseTypes.Any(baseType => baseType.IsAssignableFrom(contentType)));

            foreach (var type in types)
            {
                var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .Where(x => IsXhtmlString(x) && !NonDefaultTinyMceAttribute(x));

                foreach (var prop in properties)
                {
                    // Build expression (x => x.Propertyname)
                    var param = Expression.Parameter(type, "x");
                    var property = Expression.PropertyOrField(param, prop.Name);
                    var funcType = typeof(Func<,>).MakeGenericType(type, typeof(object));
                    var expression = Expression.Lambda(funcType, property, param);

                    // Execute config.For<Type>(expression, settings) dynamically
                    var forMethodGeneric = forMethod.MakeGenericMethod(type);
                    forMethodGeneric.Invoke(config, new object[] { expression, settings });
                }
            }
        }

        private static bool IsXhtmlString(PropertyInfo prop) => prop.PropertyType == typeof(XhtmlString);

        private static bool NonDefaultTinyMceAttribute(PropertyInfo prop)
            => prop.GetCustomAttributes(typeof(NonDefaultTinyMceAttribute), false).Any();
    }

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class NonDefaultTinyMceAttribute : Attribute
    {
    }