Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Nathan Wright 23 posts 54 karma points
    Jun 20, 2013 @ 08:10
    Nathan Wright
    0

    Prevent 'Error loading MacroEngine script' error when fields have no value

    Hi Everyone, New developer here - not new to web but new to umbraco and the windows environment. I'm building a site in Umbraco 4.11.9 at the moment. I've used the Repeatable Custom Content package to create some custom fields that allow the user to easily edit and order content. 

    I've used a CSHTML script to render out the data as HTML and put that into an accordion. All is working well -- except when one of the fields are empty I get the 'Error loading MacroEngine script' error. Is there a way I can check if the fields are available before rendering the script, and avoid the error on the pages without content in those areas? 

     

    CSHTML Code

    @using System
    @using System.Xml.Linq;
    @using System.Linq
    @using System.Collections.Generic
    @using umbraco.MacroEngines
    @inherits umbraco.MacroEngines.DynamicNodeContext

    <div class="accordion-group">
    <div class="accordion-heading">
    <a class="accordion-toggle" data-toggle="collapse" data-parent="#bottomAccordions" href="#collapseOne">You may find this information helpful</a>
    </div>
    <div id="collapseOne" class="accordion-body collapse"><div class="accordion-inner">  
    @{
           var xml = Library.ToDynamicXml(@Model.GetPropertyValue("helpfulInfo"));

            foreach(XElement item in xml.BaseElement.Elements("item")) {    
                    foreach(XElement data in item.Elements("data"))
                    {
    if (data.Attribute("alias").Value == "title")

                             {

     

                              <p class="title"><strong>@data.Value</strong></p>

                             }

    if (data.Attribute("alias").Value == "content")

                             {

                              <p class="content">@data.Value</p>

                             }

    if (data.Attribute("alias").Value == "source")

                             {

                              <p class="source"><a href="@data.Value" target="_blank">@data.Value</a></p>

                             }

                    }       

     

     

            }               

    }

     

    </div></div></div>

  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 20, 2013 @ 16:50
    Jeavon Leopold
    0

    Hi there, 

    I think you just need to check if the atrtribute is not null, e.g

    if (data.Attribute("alias") != null && data.Attribute("alias").Value == "title")

    If that doesn't work, could also post the XML you are dealing with then I should be able to work it for you.

    Thanks,

    Jeavon

  • Nathan Wright 23 posts 54 karma points
    Jun 21, 2013 @ 01:15
    Nathan Wright
    0

    Hi,

     

    Thanks for the response!! I've added that, but still getting the same error.

     

     

    @using System
    @using System.Xml.Linq;
    @using System.Linq
    @using System.Collections.Generic
    @using umbraco.MacroEngines
    @inherits umbraco.MacroEngines.DynamicNodeContext

           var xml = Library.ToDynamicXml(@Model.GetPropertyValue("helpfulInfo"));

            foreach(XElement item in xml.BaseElement.Elements("item")) {    
                   foreach(XElement data in item.Elements("data"))

                    {
    if (data.Attribute("alias") != null && data.Attribute("alias").Value == "title")

                             {

                             

    @data.Value

                             }

    if (data.Attribute("alias") != null && data.Attribute("alias").Value == "content")

     

                             {

                             

    @data.Value

                             }

     

    if (data.Attribute("alias") != null && data.Attribute("alias").Value == "source")

     

                             {

                             

    @data.Value

     

                             }

                    }       

                            

     

            }               

    }

     

  • Nathan Wright 23 posts 54 karma points
    Jun 21, 2013 @ 01:17
    Nathan Wright
    0

    Xml/Data:   
    <items>
        <item>
            <data alias="alias1">value 1</data>
            <data alias="alias2">value 2</data>
        </item>
        <item>
            <data alias="alias1">value 3</data>
            <data alias="alias2">value 4</data>
        </item>
    </items>

     

    http://our.umbraco.org/projects/backoffice-extensions/repeatable-custom-content

  • Theresa Danowski 16 posts 78 karma points
    Jun 21, 2013 @ 10:07
    Theresa Danowski
    0

    Hello Nathan,

    maybe the problem is not the empty alias but the empty value

    Try out something like these:

     

    if (data.Attribute("alias") != null && data.Attribute("alias").Value == "title" && data.Value!=null){
     <p class="title"><strong>@data.Value</strong></p>
    }

     

    Haven't tryed it out but please tell me if it works ;)

    Greets,

    Theresa

  • Nathan Wright 23 posts 54 karma points
    Jun 21, 2013 @ 10:10
    Nathan Wright
    0

    Hey thanks for your post! That doesn't seem to work either, I wonder if it's earlier? Perhaps this line needs an if statement?

     

    var xml = Library.ToDynamicXml(@Model.GetPropertyValue("helpfulInfo"));

     

     

     

     

  • Theresa Danowski 16 posts 78 karma points
    Jun 21, 2013 @ 10:19
    Theresa Danowski
    0

    That could be possible, too.

    There can be a problem while loading the xml. Maybe it return an empty xml and according to these, using the foreachs will not work, too

    You can try writing it in try{}catch(){} an test if the xml is the problem or not.

    @try{Your code here}catch(Exception e){<div>@e.Message</div>}


    That's better than just having Error-Loading-Macro Message.

  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 21, 2013 @ 10:28
    Jeavon Leopold
    0

    Here is a working snippet against the XML you posted (this is how I would do it anyway)

        var xml = Model.helpfulInfo; //will be auto converted to DynamicXml
    
        foreach (var item in xml)
        {
            if (item.Any())
            {
                foreach (var dataItem in item)
                {
                    if (dataItem.alias == "alias1" && dataItem.InnerText.Length > 0)
                    {
                        <p>@dataItem.InnerText</p>      
                    }
                }
            }
        }
  • Nathan Wright 23 posts 54 karma points
    Jun 24, 2013 @ 02:57
    Nathan Wright
    0

    Thanks everyone for your help, Jeavon your method did stop the error from appearing. However it doesn't render out the items values separately. It just renders all three as the first one. Here's my code maybe you can advise what I've done wrong.

    When I try and save I get this error

    HelpfulInfo.cshtml(37): error CS1061: 'System.Text.StringBuilder' does not contain a definition for 'append' and no extension method 'append' accepting a first argument of type 'System.Text.StringBuilder' could be found (are you missing a using directive or an assembly reference?)

     

    @using System
    @using System.Xml.Linq;
    @using System.Linq
    @using System.Collections.Generic
    @using umbraco.MacroEngines
    @inherits umbraco.MacroEngines.DynamicNodeContext
    
    
    @{
    
        var xml = Model.helpfulInfo; //will be auto converted to DynamicXml
        System.Text.StringBuilder htmlNode = new System.Text.StringBuilder();
    
                htmlNode.Append("<div class=\"accordion-group\">");
                htmlNode.Append("<div class=\"accordion-heading\">");
                htmlNode.Append("<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#bottomAccordions\" href=\"#collapseOne\">You may find this information helpful</a></div>");
                htmlNode.Append("<div id=\"collapseOne\" class=\"accordion-body collapse\"><div class=\"accordion-inner\">");
    
    
    
        foreach (var item in xml)
        {
    
    
            if (item.Any())
            {
    
    
                foreach (var dataItem in item)
                {
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"title\"><strong>"[email protected]+"</strong></p>");      
                    }
                    if (dataItem.alias == "content" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.append("<p class=\"content\">"[email protected]+"</p>");      
                    }
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.append("<p class=\"source\"><a href=\""[email protected]+"\">"[email protected]+"</a></p>");      
                    }
                }
    
    
            }
        }
    
    
      htmlNode.Append("</div></div></div>");
                htmlNode.AppendLine();
            @Html.Raw(htmlNode.ToString());         
    
    
    
    }
    
  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 24, 2013 @ 08:19
    Jeavon Leopold
    0

    Hi Nathan, could you please post the xml you are rendering agaisnt, try <pre>@Model.helpfulInfo.ToXml().ToString()</pre>to get it.

    Thanks,

    Jeavon

  • Nathan Wright 23 posts 54 karma points
    Jun 24, 2013 @ 08:39
    Nathan Wright
    0

    Hi Jeavon,

     

    They look like this - using those alias's, title, content and source. 

    <items>
        <item>
            <data alias="title">value 1</data>
            <data alias="content">value 2</data>
    <data alias="source">value 2</data> 
        </item>
    </items>


  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 24, 2013 @ 10:08
    Jeavon Leopold
    0

    Ah ok, just a couple of tiny tweaks required:

     @{
        var xml = Model.helpfulInfo; //will be auto converted to DynamicXml
        System.Text.StringBuilder htmlNode = new System.Text.StringBuilder();
    
        htmlNode.Append("<div class=\"accordion-group\">");
        htmlNode.Append("<div class=\"accordion-heading\">");
        htmlNode.Append("<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#bottomAccordions\" href=\"#collapseOne\">You may find this information helpful</a></div>");
        htmlNode.Append("<div id=\"collapseOne\" class=\"accordion-body collapse\"><div class=\"accordion-inner\">");
    
    
        foreach (var item in xml)
        {
            if (item.Any())
            {
                foreach (var dataItem in item)
                {
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"title\"><strong>" + @dataItem.InnerText + "</strong></p>");
                    }
                    if (dataItem.alias == "content" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"content\">" + @dataItem.InnerText + "</p>");
                    }
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"source\"><a href=\"" + @dataItem.InnerText + "\">" + @dataItem.InnerText + "</a></p>");
                    }
                }
            }
        }
    
        htmlNode.Append("</div></div></div>");
        htmlNode.AppendLine();
        @Html.Raw(htmlNode.ToString());         
    
    }

     

  • Nathan Wright 23 posts 54 karma points
    Jun 25, 2013 @ 01:50
    Nathan Wright
    0

    Thanks, that works great - but needs to have the htmlNodes part of an in statement too - so they only render if the item has value, but only once, not per item.

    Here's what I've tried... doesn't seem to be working though

     

     @{
        var xml = Model.helpfulInfo; //will be auto converted to DynamicXml
        System.Text.StringBuilder htmlNode = new System.Text.StringBuilder();
     
     if (xml = null) {
     
    htmlNode.Append("<div class=\"accordion-group\">");
        htmlNode.Append("<div class=\"accordion-heading\">");
        htmlNode.Append("<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#bottomAccordions\" href=\"#collapseOne\">You may find this information helpful</a></div>");
        htmlNode.Append("<div id=\"collapseOne\" class=\"accordion-body collapse\"><div class=\"accordion-inner\">");
     }
     
        foreach (var item in xml)
        {
            if (item.Any())
            {
                foreach (var dataItem in item)
                {
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"title\"><strong>" + @dataItem.InnerText + "</strong></p>");
                    }
                    if (dataItem.alias == "content" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"content\">" + @dataItem.InnerText + "</p>");
                    }
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"source\"><a href=\"" + @dataItem.InnerText + "\">" + @dataItem.InnerText + "</a></p>");
                    }
                }
            }
        }
     if (xml != null) {
        htmlNode.Append("</div></div></div>");
        htmlNode.AppendLine();
        @Html.Raw(htmlNode.ToString());         
     }
    }
  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 25, 2013 @ 10:05
    Jeavon Leopold
    0

    Hi Nathan,

    I think you are just looking for the .Any() method, e.g.

     @{
        var xml = Model.helpfulInfo; //will be auto converted to DynamicXml
        System.Text.StringBuilder htmlNode = new System.Text.StringBuilder();
    
        if (xml.Any())
        {
    
            htmlNode.Append("<div class=\"accordion-group\">");
            htmlNode.Append("<div class=\"accordion-heading\">");
            htmlNode.Append("<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#bottomAccordions\" href=\"#collapseOne\">You may find this information helpful</a></div>");
            htmlNode.Append("<div id=\"collapseOne\" class=\"accordion-body collapse\"><div class=\"accordion-inner\">");
        }
    
        foreach (var item in xml)
        {
            if (item.Any())
            {
                foreach (var dataItem in item)
                {
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"title\"><strong>" + @dataItem.InnerText + "</strong></p>");
                    }
                    if (dataItem.alias == "content" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"content\">" + @dataItem.InnerText + "</p>");
                    }
                    if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                    {
                        htmlNode.Append("<p class=\"source\"><a href=\"" + @dataItem.InnerText + "\">" + @dataItem.InnerText + "</a></p>");
                    }
                }
            }
        }
        if (xml.Any())
        {
            htmlNode.Append("</div></div></div>");
            htmlNode.AppendLine();
             @Html.Raw(htmlNode.ToString());
        }
    }

     Thanks,

    Jeavon

  • Nathan Wright 23 posts 54 karma points
    Jun 26, 2013 @ 01:14
    Nathan Wright
    0

    Hi Jeavon,

     

    Thanks! I think that's exactly what I need... except now it displays the original error again - 'error loading macro' :S

    Any ideas?

     

     

    Thanks

  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 26, 2013 @ 11:04
    Jeavon Leopold
    0

    Hi Nathan,

    That's odd, I've been trying to break this code and it seems pretty good. Anyway, below is a even more bullet proof version that will also give us some info if it still errors:

     @{
        try
        {
            var xml = Model.helpfulInfo; //will be auto converted to DynamicXml
    
            if (Model.HasValue("helpfulInfo"))
            {
                System.Text.StringBuilder htmlNode = new System.Text.StringBuilder();
    
                if (xml != null && xml.Any())
                {
                    htmlNode.Append("<div class=\"accordion-group\">");
                    htmlNode.Append("<div class=\"accordion-heading\">");
                    htmlNode.Append("<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#bottomAccordions\" href=\"#collapseOne\">You may find this information helpful</a></div>");
                    htmlNode.Append("<div id=\"collapseOne\" class=\"accordion-body collapse\"><div class=\"accordion-inner\">");
                }
    
                foreach (var item in xml)
                {
                    if (item.Any())
                    {
                        foreach (var dataItem in item)
                        {
                            if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                            {
                                htmlNode.Append("<p class=\"title\"><strong>" + @dataItem.InnerText + "</strong></p>");
                            }
                            if (dataItem.alias == "content" && dataItem.InnerText.Length > 0)
                            {
                                htmlNode.Append("<p class=\"content\">" + @dataItem.InnerText + "</p>");
                            }
                            if (dataItem.alias == "title" && dataItem.InnerText.Length > 0)
                            {
                                htmlNode.Append("<p class=\"source\"><a href=\"" + @dataItem.InnerText + "\">" + @dataItem.InnerText + "</a></p>");
                            }
                        }
                    }
                }
                if (xml != null && xml.Any())
                {
                    htmlNode.Append("</div></div></div>");
                    htmlNode.AppendLine();
                    @Html.Raw(htmlNode.ToString());
                }
    
            }
    
        }
        catch (Exception e)
        {
            <div style="color:red">@e.Message<br/>
    
                @if (Model.HasValue("helpfulInfo"))
                {
                    if (Model.helpfulInfo.GetType() == typeof (DynamicXml))
                    {
                        <pre style="color:red">@Model.helpfulInfo.ToXml().ToString()</pre>
                    }
                    else
                    {
                        <pre style="color:red">@Model.helpfulInfo</pre>  
                    }              
                }                       
            </div>
        }
    
    }

    Hopefully this will work, if not at least we should be able to see what the error is.

    Jeavon

  • Nathan Wright 23 posts 54 karma points
    Jun 27, 2013 @ 02:38
    Nathan Wright
    0

    Hi Jeavon,

     

    Thanks again for your efforts, when I try saving that I get this error

    c:\inetpub\sites\macroScripts\635079259914952463_HelpfulInfo.cshtml(55): error CS0246: The type or namespace name 'DynamicXml' could not be found (are you missing a using directive or an assembly reference?)

  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 27, 2013 @ 08:06
    Jeavon Leopold
    0

    Ah you need to add @using umbraco.MacroEngines at the top of you script

  • Nathan Wright 23 posts 54 karma points
    Jun 27, 2013 @ 08:14
    Nathan Wright
    1

    Success!!!!!!! Thankyou!

    :)
  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 27, 2013 @ 08:16
    Jeavon Leopold
    0

    Awesome!

Please Sign in or register to post replies

Write your reply to:

Draft