Dynamically defined content sections in Razor views

I am trying to implement a thought that I should have allowed to dynamically generate custom sections for my MVC 3 Razor site.

The template will look something like this.

<div class="sidebar"> @RenderSection("Sidebar", false) </div> <div class="content"> @RenderSection("MainContent", false) @RenderBody() </div> 

Adding a view with the following code gives me the result I would expect

 DefineSection("MainContent", () => { this.Write("Main Content"); }); DefineSection("Sidebar", () => { this.Write("Test Content"); }); 

Conclusion:

 <div class="sidebar">Test Content </div> <div class="content">Main Content <p>Rendered body from view</p></div> 

Looking at this, it seemed easy enough to create a Dictionary<SectionName, Dictionary<ControlName, Model>>

 var sectionControls = new Dictionary<string, Dictionary<string, dynamic>>(); sectionControls.Add("MainContent", new Dictionary<string, dynamic>() { {"_shoppingCart", cart} }); sectionControls.Add("Sidebar", new Dictionary<string, dynamic>() { { "_headingImage", pageModel.HeadingImage }, { "_sideNav", null } }); pageModel.SectionControls = sectionControls; 

Thus, the above code declares two sections of the templates ("MainContent" with a cart and a "side panel" with image and navigation.

So now my view contains code to render the output like this:

 foreach(KeyValuePair<string,Dictionary<string,dynamic>> section in Model.SectionControls) { DefineSection(section.Key, () => { foreach (KeyValuePair<string, dynamic> control in section.Value) { RenderPartialExtensions.RenderPartial(Html, control.Key, control.Value); } }); } 

Now, when I run this code, both sections contain the same content! The passage of the code shows that the download path is as follows:

Action Returns, the code above works in the view, LayoutTemlpate starts loading. when a RenderSection is called for these two sections in the layout template, the view starts again! It seems even stranger to me that the end result is that the “HeadingImage” and “SideNav” fall into the Sidebar and MainContent sections. The MainContent section does not contain a basket; it contains a duplicate of the sidebar section.

 <div class="sidebar"> <h2><img alt=" " src="..."></h2> ..nav.. </div> <div class="content"> <h2><img alt=" " src="..."></h2> ..nav.. <p>Rendered body from view</p> </div> 

Commenting on one of the two definitions of the section in the controller, the other is the only element (but it is still duplicated!)

Has anyone had this problem before or knew what restriction could cause this behavior?

Edit: Great. Thanks for the connection! I am afraid for a new version of resharper with razor support.

+6
source share
1 answer

Your lambda expressions use the same section variable.
When lambda is called, the current value of the variable is the last section.

You need to declare a separate variable inside the loop .

 foreach(KeyValuePair<string,Dictionary<string,dynamic>> dontUse in Model.SectionControls) { var section = dontUse; DefineSection(section.Key, () => { foreach (KeyValuePair<string, dynamic> control in section.Value) { RenderPartialExtensions.RenderPartial(Html, control.Key, control.Value); } }); } 
+6
source

Source: https://habr.com/ru/post/890524/


All Articles