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?
<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")
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>
}
}
}
}
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());
}
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();
htmlNode.Append("<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#bottomAccordions\" href=\"#collapseOne\">You may find this information helpful</a></div>");
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.
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?)
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>
Hi there,
I think you just need to check if the atrtribute is not null, e.g
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
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
You may find this information helpful
@{
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
}
}
}
}
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
Hello Nathan,
maybe the problem is not the empty alias but the empty value
Try out something like these:
Haven't tryed it out but please tell me if it works ;)
Greets,
Theresa
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"));
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.
That's better than just having Error-Loading-Macro Message.
Here is a working snippet against the XML you posted (this is how I would do it anyway)
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?)
Hi Nathan, could you please post the xml you are rendering agaisnt, try <pre>@Model.helpfulInfo.ToXml().ToString()</pre>to get it.
Thanks,
Jeavon
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>
Ah ok, just a couple of tiny tweaks required:
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
Hi Nathan,
I think you are just looking for the .Any() method, e.g.
Thanks,
Jeavon
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
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:
Hopefully this will work, if not at least we should be able to see what the error is.
Jeavon
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?)
Ah you need to add @using umbraco.MacroEngines at the top of you script
Success!!!!!!! Thankyou!
:)
Awesome!
is working on a reply...