Open verdie-g opened 10 months ago
I'm afraid you can't do this:
<FluentTreeView>
@{
RenderTree(0, 3);
void RenderTree(int depth, int maxDepth)
{
if (depth >= maxDepth)
{
return;
}
<FluentTreeItem Text="item">
@{ RenderTree(depth + 1, maxDepth); }
</FluentTreeItem>
}
}
</FluentTreeView>
This is adding procedural logic in the middle of rendering that shares the same RenderTreeBuilder
just as a fluke of C# scoping rules. It will write output to the builder in an unsupported order, without any correctness guarantees provided by normal Razor syntax. It's unfortunate that C# local method syntax creates the possibility of this pattern which will not work.
It could be an error with the library (initially reported here https://github.com/microsoft/fluentui-blazor/issues/1289) but this code works fine:
That does work fine because it's returning a real RenderFragment
which can be rendered properly.
So why does it seem to work fine with div
elements? 🤔
<div>
@{
RenderTree(0, 3);
void RenderTree(int depth, int maxDepth)
{
if (depth >= maxDepth)
{
return;
}
<div>
item
@{ RenderTree(depth + 1, maxDepth); }
</div>
}
}
</div>
Also is it possible to detect that and throw a proper error?
Rendering an HTML element and rendering a child component are very different. It's still not supported to do this for <div>
even if it happens to work by chance in this case.
Also is it possible to detect that and throw a proper error?
That would be good. I'll update the issue title to match.
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
[Edit by @SteveSandersonMS] This issue was originally reported by @verdie-g as follows below the line. On investigation the problem is that C# has added a new syntax that doesn't work in Razor.
The Razor compiler allows arbitrary C# code within
@{ ... }
blocks. Unfortunately this means it allows the use of local functions in a way that confuses the parsing logic, causing it to use the wrong__builder
instance. Example:Here, the child content of
FluentTreeItem
should be compiled as aRenderFragment
that acts on whateverRenderTreeBuilder
is passed in. But because of C# scoping rules, theRenderFragment
actually acts on the__builder
captured from its parent context, so it is simply corrupting the output instead of doing something useful.Possible solutions:
@{ ... }
specifically. However that's probably impractical because Razor doesn't parse the contents of@{ ... }
.RenderTreeBuilder
is invoked. For example if the runtime set an "rendering in progress" flag on it before it starts rendering and synchronously unsets that flag at the end of rendering, then it would have caught this case because child components are rendered afterwards (not recursively), so when the child is rendered it would see it's trying to write to a builder that does not have the "rendering in progress" flag set.NullReferenceException
instead of corrupt output. Obviously that's not super easy to understand but avoids any perf cost.Is there an existing issue for this?
Describe the bug
I'm rendering a blazor wasm component using a recursive C# method and while it's working fine using C# only (
OpenComponent
,AddAttribute
, etc.), it fails when returning HTML from that recursive method.Expected Behavior
I'm expecting a tree structure to be built and clicking on a line should expand its children but it seems like the children are not rendered and an error is thrown on click.
Steps To Reproduce
I was not able to reproduce the issue without the library fluentui-blazor.
Then replace
Home.razor
withClick on the item generated and check the error in the console.
It could be an error with the library (initially reported here https://github.com/microsoft/fluentui-blazor/issues/1289) but this code works fine:
Exceptions (if any)
.NET Version
8.0.101
Anything else?
No response