0
votes

I am having a weird issue, hoping you all have some pointers. I am using Umbraco 4.11.10 and trying to fulfill a requirement to display 1 random quote from a collection of quotes. The really puzzling thing is that this exact code works on a different site using the same version of Umbraco.
The Quote object only has two properties...quoteText and quoteSignature. Here is my entire razor script (which currently fails).

@inherits umbraco.MacroEngines.DynamicNodeContext

@{
     var item = @Model.NodeById(1113).Children.Random();
     <div>
          <blockquote>@item.quoteText<span>- @item.quoteSignature</span></blockquote>
     </div>
}

If I strip out the div and block quote and all of that and just leave

var item = @Model.NodeById(1113).Children.Random();

it still fails.

If I remove Random() and output the @item variable it is a DynamicNodeList. If I do something like..

foreach(var child in item)
{
     <div>
          <blockquote>@child.quoteText<span>- @child.quoteSignature</span></blockquote>
     </div>
}

It works, but of course I get all of the quotes. So I guess that at least proves that the data is valid, and the property names are valid. Just seems to be an issue using Random(). As I am pretty new to Razor I'm hoping this is just an oversight on my part.

*UPDATE * The error from the error log is as follows

2013-09-03 19:34:00,142 [11] WARN  umbraco.macro - [Thread 24] Error loading MacroEngine script (file: CFRandomQuote.cshtml, Type: ''. Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'umbraco.MacroEngines.DynamicNodeList' does not contain a definition for 'Random'
   at CallSite.Target(Closure , CallSite , Object , Int32 )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at ASP._Page_macroScripts_CFRandomQuote_cshtml.Execute() in c:\inetpub\cf\macroScripts\CFRandomQuote.cshtml:line 5
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
   at System.Web.WebPages.WebPage.ExecutePageHierarchy()
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
   at umbraco.MacroEngines.RazorMacroEngine.ExecuteRazor(MacroModel macro, INode currentPage)
   at umbraco.MacroEngines.RazorMacroEngine.Execute(MacroModel macro, INode currentPage)
   at umbraco.macro.loadMacroScript(MacroModel macro)
   at umbraco.macro.renderMacro(Hashtable pageElements, Int32 pageId)

Thanks Everyone!

3
Should that be @child.quoteText etc. in the code not @item.?Digbyswift
yep - copy paste error. I updated the snippet - thanks!hardba11
Could you update the question with the error from the log files? There should be a stack trace showing what the error is. They're located at ~/app_data/logs/Digbyswift
thanks @Digbyswift - I added the error. The important part of that message - 'umbraco.MacroEngines.DynamicNodeList' does not contain a definition for 'Random' - is perplexing as I know it does support random and has for awhile now. An outdated RazorEngine dll perhaps?hardba11
after looking through the dll's I guess the newer builds don't use the RazorEngine.dll anymore. It has System.Web.WebPages.Razor.dll and System.Web.Razor.dll. And on goes the search...hardba11

3 Answers

1
votes

I don't think it's necessarily a discrepancy in the DLLs. i've hecked through the v6 source and the Random() code is still there.

It's part of the umbraco.MacroEngines.ExtensionMethods class:

public static DynamicNode Random(this DynamicNodeList all)
{
    return all.Items.OrderBy(x => Guid.NewGuid()).First();
}

So the problem would seem to be that your macro is not referencing the namespace umbraco.MacroEngines. Put the following code into your macro, either before or after the @inherits:

@using umbraco.MacroEngines

If this doesn't work then just implement the query long-hand:

@Model.NodeById(1113).ChildrenAsList
                     .OrderBy(n => Guid.NewGuid())
                     .FirstOrDefault()
0
votes

How about this:

var randomQuote = Library.NodeById(1113).ChildrenAsList.Items.GetRandom(1);

I think Model.NodeById is obsolete.

0
votes

I had a similar problem. I solved it by passing a number of items to return into the .Random() method. EG:

var galleryItems = imageGallery.Children.Random(50);

Or in your case (in theory):

var item = @Model.NodeById(1113).Children.Random(1);

However, if you do this, you'll receive a list with one item, so you probably need:

var item = @Model.NodeById(1113).Children.Random(1).Take(1);