How I hack the Macro Container into working with MVC

I made a little model class for a macro, this contains the name of the macro and a dictionary of its properties.

public class UmbracoMacro
    {
        public string Name { getset; }
 
        public IDictionary<stringobject> Properties { getset; }
    }

I then created a class that would convert the macro string into the UmbracoMacro object I created.

public class MacroTagParser
    {
        public static UmbracoMacro GetMacroFromTag(string tag)
        {
            var sb = new StringBuilder();
            var macro = new UmbracoMacro();
 
            ParseMacros(
                    tag,
                    textBlock => sb.Append(textBlock),
                    (macroAliasmacroAttributes=> macro = new UmbracoMacro
                    {
                        Name = macroAlias,
                        Properties = ConvertTo(macroAttributesx => (string)xx => (object)x)
                    }
            );
 
            return macro;
        }
 
        public static IDictionary<TKeyOut, TValOut> ConvertTo<TKeyOutTValOut>(IDictionary dFunc<object, TKeyOut> keyConverterFunc<object, TValOut> valConverter)
        {
            var result = new Dictionary<TKeyOut, TValOut>();
            foreach (DictionaryEntry v in d)
            {
                result.Add(keyConverter(v.Key), valConverter(v.Value));
            }
            return result;
        }
 
        internal static void ParseMacros(
            string text,
            Action<string> textFoundCallback,
            Action<stringDictionary<stringstring>> macroFoundCallback)
        {
            if (textFoundCallback == nullthrow new ArgumentNullException("textFoundCallback");
            if (macroFoundCallback == nullthrow new ArgumentNullException("macroFoundCallback");
 
            string elementText = text;
 
            var fieldResult = new StringBuilder(elementText);
 
            //NOTE: This is legacy code, this is definitely not the correct way to do a while loop! :)
            var stop = false;
            while (!stop)
            {
                var tagIndex = fieldResult.ToString().ToLower().IndexOf("<?umbraco");
                if (tagIndex < 0)
                    tagIndex = fieldResult.ToString().ToLower().IndexOf("<umbraco:macro");
                if (tagIndex > -1)
                {
                    var tempElementContent = "";
 
                    //text block found, call the call back method
                    textFoundCallback(fieldResult.ToString().Substring(0tagIndex));
 
                    fieldResult.Remove(0tagIndex);
 
                    var tag = fieldResult.ToString().Substring(0fieldResult.ToString().IndexOf(">"+ 1);
                    var attributes = XmlHelper.GetAttributesFromElement(tag);
 
                    // Check whether it's a single tag (<?.../>) or a tag with children (<?..>...</?...>)
                    if (tag.Substring(tag.Length - 21!= "/" && tag.IndexOf(" "> -1)
                    {
                        String closingTag = "</" + (tag.Substring(1tag.IndexOf(" "- 1)) + ">";
                        // Tag with children are only used when a macro is inserted by the umbraco-editor, in the
                        // following format: "<?UMBRACO_MACRO ...><IMG SRC="..."..></?UMBRACO_MACRO>", so we
                        // need to delete extra information inserted which is the image-tag and the closing
                        // umbraco_macro tag
                        if (fieldResult.ToString().IndexOf(closingTag> -1)
                        {
                            fieldResult.Remove(0fieldResult.ToString().IndexOf(closingTag));
                        }
                    }
 
                    var macroAlias = attributes.ContainsKey("macroalias"? attributes["macroalias"] : attributes["alias"];
 
                    //call the callback now that we have the macro parsed
                    macroFoundCallback(macroAliasattributes);
 
                    fieldResult.Remove(0fieldResult.ToString().IndexOf(">"+ 1);
                    fieldResult.Insert(0tempElementContent);
                }
                else
                {
                    //text block found, call the call back method
                    textFoundCallback(fieldResult.ToString());
 
                    stop = true//break;
                }
            }
        }
    }

To use it in a macro I just do this:

var hack = Umbraco.Field("macroName").ToString();
                    
var macro = Samson.Model.UmbracoHelpers.MacroTagParser.GetMacroFromTag(hack);
 
@Umbraco.RenderMacro(macro.Namemacro.Properties);

I imagine that I have just done something wrong which has caused the error to occur, but just incase it isn't just me, I thought I'd put this online in case others are in need for it.

Update

Turns out there is an easier way. In the Umbraco Library helpers there is this method that can be used to display the macros from a macro container.

@Html.Raw(umbraco.library.RenderMacroContent(CurrentPage.{nameOfPageField}, CurrentPage.Id))

 

Comments

comments powered by Disqus