DynamicNodeList.Where marked as private in 4.7final
So, I just upgraded from 4.7RC to 4.7final, and BAM, my site came crashing down.
It seems that the DynamicNodeList.Where, which I use a few places.... is suddently marked as private... Is this intentional? And if so, what should I use instead?
Can't test anything at the moment, but a quick look at the source on codeplex shows that it was changed to private to force you to go through the DynamicObjects TryInvokeMember, which is overridden, I assume to better handle the Where's arguments.
Can you provide a code sample of what you are trying to achieve, what are you passing to the Where method?
I also did a quick look, but can't find anything on the subject, could you elaborate on where you found this?
I could provide you with examples, but the most common, I guess, would be @Model.Children.Where("something")
All the examples from the Umbraco blog uses this syntax, so I'm quite puzzled about this. Any information you or others could bring to this would be highly appreciated.
I found it on codeplex by looking at Gareth's (agrath) latest merge here
You can see by the diff that the scope of Where and OrderBy were both changed to private. Did I see earlier that someone was also having problems with OrderBy on here?
So when you do DynamicNodeList.Where() in theory the TryInvokeMember override should fire with a binder.Name of "Where" which should then (eventually) pass you through to the private Where() Method.
That's my understanding of it anyway, so either the TryInvokeMember isn't firing, or something else is going wrong once you are in it. I don't have a lot of experience with DynamicObject but could it be that because there is already a Where method (even though it is private) that TryInvokeMember doesn't get called? I would have thought the guys would have tested it was working though. Which is why I thought perhaps the parameters you were passing were causing it to try to access the private method. What error message do you get?
Wihtout being able to test (which I can't at the moment) it's hard to help more than that, sorry.
Alex, thank you for shedding some light on this. Indeed DynamicNodeList.Where() does work as expected as long as everything is dynamic.
Once you start toying around with instances of DynamicNodeList, the Where method though, is kinda missed. I do realize I can work directly on the Items collections instead, but it really ain't as pretty. Perhaps I should rethink my approach :)
Yes, as I wrote just before, the @Model.Children.Where() approach works just find, as the TryInvokeMember does indeed fire the Where method. I was trying to access Where from an instance of DynamicNodeList as such:
var list = new DynamicNodeList(); list.Where("something");
Which I could not do. Lacking knowledge of the TryInvokeMember method, I simply assumed that the Where method would'nt be available on the dynamic type either, I was wrong :)
Again, thank you for pointing me in the right direction.
There are numorous ways to work around it. So far I have simply made a few extension methods which access the DynamycNodeList.Items collection directly like the example below:
var node = new DynamicNode(1090);
node.GetChildrenAsList.Items.AsQueryable().Where("NodeTypeAlias == \"Content\"")
The Where method is really just a wrapper around this functionality anyways :)
What about when there is more than one condition in the lambda predicate?
This used to work in 4.7RC
var maxLevelForSitemap = 3;
var values = newDictionary<string,object>();
values.Add("maxLevelForSitemap", maxLevelForSitemap);
var items = node.Children.Where("umbracoNaviHide != true && level <= maxLevelForSitemap", values)
But after with the 4.7 final version it retuns Error loading Razor Script RecursiveMenu.cshtml Incorrect number of parameters supplied for lambda declaration the only way around I found is
var maxLevelForSitemap = 3;
var values = newDictionary<string,object>();
values.Add("maxLevelForSitemap", maxLevelForSitemap);
var items = node.GetChildrenAsList.Where(@"umbracoNaviHide != true").Where(@"level <= maxLevelForSitemap", values);
This is OK, but ideally I would like to use only one Where() statement as before. Any one any idea?
Yes, I made .OrderBy and .Where private when I implemented InvokeMember, but the .AsQueryable solution is the correct way to approach this, or as you've discovered, make the variable dynamic.
The && issue above will be sorted, I changed the way some properties were accessed in the expression tree and I think that's what broke this and OrderBy
DynamicNodeList.Where marked as private in 4.7final
So, I just upgraded from 4.7RC to 4.7final, and BAM, my site came crashing down.
It seems that the DynamicNodeList.Where, which I use a few places.... is suddently marked as private... Is this intentional? And if so, what should I use instead?
Kind regards
Mads
Same problem here!!
Shameless bump
Hi,
Can't test anything at the moment, but a quick look at the source on codeplex shows that it was changed to private to force you to go through the DynamicObjects TryInvokeMember, which is overridden, I assume to better handle the Where's arguments.
Can you provide a code sample of what you are trying to achieve, what are you passing to the Where method?
Hi Alex
I also did a quick look, but can't find anything on the subject, could you elaborate on where you found this?
I could provide you with examples, but the most common, I guess, would be @Model.Children.Where("something")
All the examples from the Umbraco blog uses this syntax, so I'm quite puzzled about this.
Any information you or others could bring to this would be highly appreciated.
I found it on codeplex by looking at Gareth's (agrath) latest merge here
You can see by the diff that the scope of Where and OrderBy were both changed to private. Did I see earlier that someone was also having problems with OrderBy on here?
So when you do DynamicNodeList.Where() in theory the TryInvokeMember override should fire with a binder.Name of "Where" which should then (eventually) pass you through to the private Where() Method.
That's my understanding of it anyway, so either the TryInvokeMember isn't firing, or something else is going wrong once you are in it. I don't have a lot of experience with DynamicObject but could it be that because there is already a Where method (even though it is private) that TryInvokeMember doesn't get called? I would have thought the guys would have tested it was working though. Which is why I thought perhaps the parameters you were passing were causing it to try to access the private method. What error message do you get?
Wihtout being able to test (which I can't at the moment) it's hard to help more than that, sorry.
Alex, thank you for shedding some light on this.
Indeed DynamicNodeList.Where() does work as expected as long as everything is dynamic.
Once you start toying around with instances of DynamicNodeList, the Where method though, is kinda missed.
I do realize I can work directly on the Items collections instead, but it really ain't as pretty. Perhaps I should rethink my approach :)
Hi Mads,
Finally was able to test and the following works fine for me.
Hi Alex
Yes, as I wrote just before, the @Model.Children.Where() approach works just find, as the TryInvokeMember does indeed fire the Where method.
I was trying to access Where from an instance of DynamicNodeList as such:
var list = new DynamicNodeList();
list.Where("something");
Which I could not do. Lacking knowledge of the TryInvokeMember method, I simply assumed that the Where method would'nt be available on the dynamic type either, I was wrong :)
Again, thank you for pointing me in the right direction.
Ah ok, now I am with you. You are right this doesn't work. Perhaps Gareth or someone else can tell us why?
But you can do this, which you have probably already figured out, which may help you out.
There are numorous ways to work around it. So far I have simply made a few extension methods which access the DynamycNodeList.Items collection directly like the example below:
The Where method is really just a wrapper around this functionality anyways :)
Well at the very least it made me brush up on my knowledge of DynamicObject and dynamic vs var! Good stuff!
Hehe same thing here :)
What about when there is more than one condition in the lambda predicate?
This used to work in 4.7RC
But after with the 4.7 final version it retuns Error loading Razor Script RecursiveMenu.cshtml Incorrect number of parameters supplied for lambda declaration the only way around I found is
This is OK, but ideally I would like to use only one Where() statement as before. Any one any idea?
Interesting problem.
I havent had the time to properly debug/reflector through the code to get an idea of why this aint working, so any suggestions are welcomed.
I though we can see the actual in the codeplex source code browser?
Hi Guys
Yes, I made .OrderBy and .Where private when I implemented InvokeMember, but the .AsQueryable solution is the correct way to approach this, or as you've discovered, make the variable dynamic.
The && issue above will be sorted, I changed the way some properties were accessed in the expression tree and I think that's what broke this and OrderBy
Sorry :)
Hey Gareth,
Thank you for replying, good to know the && issue will be fixed! :)
is working on a reply...