Added documentElement checking to DynamicXml convert for DynamicNode property get to solve a potential issue with XHTML RTEs
Fixed issue with calling @Model.Children.First() in testing (null Children in testing)
Put some commented placeholder code in .XPath->DynamicNodeList inside DynamicNode.cs for future return of DynamicXml if not valid List<NodeFactory.Node>
Decided that if using @Model.XPath and you were in testing, then the resulting DynamicNodeList should contain self/this, not be empty
Should allow chaining to work when in test mode
Fixed a potential issue when DynamicNode got returned during testing because there are no children
and then property accesses would return false causing chaining to break
Added [a somewhat experimental] DynamicXml and xml fragment detection within DynamicNode to DynamicXml,
When accessing a string property that contains XML, you can now continue your dot based access
Call .ToXml() to get the real XML string again
Call .XPath(string) to run a XPath query on the fragment and return another DynamicXml
Example:
<Catalog>
<Book id="bk101">
<Author>Garghentini, Davide</Author>
<Title>XML Developer's Guide</Title>
<Genre>Computer</Genre>
...
@Model.Children.Random().someXmlProperty.Catalog.Book[1].Genre
@Model.Children.Random().someXmlProperty.Book[1].XPath(".//Genre")
@Model.Children.Random().someXmlProperty.Book[1].ToXml()
Nodes are attempted to be turned back into NodeFactory.Node when returned by XPath and then wrapped in DynamicNode and then DynamicNodeList
Added .Random parameterless overload to pick a single random node from the DynamicNodeList
Example of new Methods being used:
<img src='@Model.XPath("//ChildItem[catCount = 2]").Random().Media("catPicture","umbracoFile")'/>
Usage is: @foreach(var item in home.ChildItems.OrderBy("catCount, colour desc"))
If you use the simple form of home.ChildItems.OrderBy("catCount") it will use a simpler/faster implementation
Only supports single pass, ascending currently, so no ThenBy implementation or Descending variants
The original query parser supports OrderBy("catCount, name desc") by nesting Expression.Call
Current implementation for DynamicNodeList supports OrderBy("catCount") only
Simplified SQL query used for property type lookup
Added cache clearing for propertyType cache when ContentType.ClearCache is called
Improves performance of new razor property lookups - most improvement on large sets
Caused user-loaded extension methods on DynamicNodeList to be pretty unreliable (would work sometimes, sometimes wouldn't find method - particularly after an iisreset)
Changed this to a return true
Replaced some API calls via Document & Property (database level, not nodefactory) with a single SQL scalar where I was getting the control type (to determine if "0"/"1" should actually be "true"/"false")
Should perform a lot better now
Already had support for YesNoType (where the string value is 1 or 0) being converted/parsed to boolean
Added some TryParse calls to int and decimal respecitvely so that if a IProperty.Value is a valid decimal or int it will be returned from DynamicNode.TryGetMember as such
This enables the .Where operator to have the correct type after property retrieval so that some numerical comparisons will work
Added support for >, >=, <, <= and %[mod] to .Where
@Model.Children.Where("catCount > 1")
@Model.Children.Where("catCount % 2 == 0")
Refactored GenerateEqual into a Factory method HandleDynamicNodeLambdas that takes an ExpressionType
Implemented Expression.NotEqual
@Model.Children.Where("shouldBeVisible != true") => children that are hidden
e.g. @Model.Children.Where("shouldBeVisible == true")
Also changed internal where implementation to handle Func<DynamicNode,bool> as well as Func<DynamicNode,object>
Both left & right side as lambda expressions should work (though I haven't tested this yet)
e.g. @Model.Children.Where("property1 == property2")
Only == (Expression.Equals) is supported currently due to the extra code required to invoke the lambda when generating the final comparison expression
e.g. @Model.Children.Where(node=>node.shouldBeVisible)
To solve this, I used the DynamicQueryable class from the Linq samples which has a parser that can take a string then modified the internals a bit so
that if your object is a DynamicObject, an additional expression tree is generated which calls the TryGetMember on it
The end result is that you can now do this [I have Random(this DynamicNodeList nodes, int max) in my bin folder]
@Model.Children.Where("shouldBeVisible").Random(2) => two nodes, randomly picked, from the ones that should be visible
*Only* Where is implemented here currently, I'll add support by OrderBy and ThenBy after I've tested some more complex scenarios.
I need to fix a small issue with my DynamicLoading of extensions - under some scenarios the class doesn't get found and i'm not sure why.