Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit a06a1d0

Browse files
author
N. Taylor Mullen
committed
Rebased and addressed code review comments.
1 parent 99f2c84 commit a06a1d0

File tree

10 files changed

+107
-92
lines changed

10 files changed

+107
-92
lines changed

src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContext.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
1212
/// </summary>
1313
public class TagHelperContext
1414
{
15+
private readonly Func<Task<string>> _getChildContentAsync;
16+
1517
/// <summary>
1618
/// Instantiates a new <see cref="TagHelperContext"/>.
1719
/// </summary>
@@ -22,7 +24,7 @@ public TagHelperContext([NotNull] IDictionary<string, object> allAttributes,
2224
[NotNull] Func<Task<string>> getChildContentAsync)
2325
{
2426
AllAttributes = allAttributes;
25-
GetChildContentAsync = getChildContentAsync;
27+
_getChildContentAsync = getChildContentAsync;
2628
}
2729

2830
/// <summary>
@@ -33,9 +35,13 @@ public TagHelperContext([NotNull] IDictionary<string, object> allAttributes,
3335
/// <summary>
3436
/// A delegate used to execute and retrieve the rendered child content asynchronously.
3537
/// </summary>
38+
/// <returns>Content rendered by children.</returns>
3639
/// <remarks>
3740
/// Child content is only executed once. Successive calls to this delegate return a cached result.
3841
/// </remarks>
39-
public Func<Task<string>> GetChildContentAsync { get; }
42+
public Task<string> GetChildContentAsync()
43+
{
44+
return _getChildContentAsync();
45+
}
4046
}
4147
}

src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
1414
public class TagHelperExecutionContext
1515
{
1616
private readonly List<ITagHelper> _tagHelpers;
17-
private string _childContent;
17+
private readonly Func<Task> _executeChildContentAsync;
18+
private readonly Action _startWritingScope;
19+
private readonly Func<TextWriter> _endWritingScope;
20+
private string _childContent;
1821

1922
/// <summary>
2023
/// Internal for testing purposes only.
2124
/// </summary>
2225
internal TagHelperExecutionContext(string tagName)
2326
: this(tagName,
24-
executeChildContentAsync: async () => await Task.FromResult(result: true),
27+
executeChildContentAsync: () => Task.FromResult(result: true),
2528
startWritingScope: () => { },
2629
endWritingScope: () => new StringWriter())
2730
{
@@ -39,37 +42,16 @@ public TagHelperExecutionContext([NotNull] string tagName,
3942
[NotNull] Action startWritingScope,
4043
[NotNull] Func<TextWriter> endWritingScope)
4144
{
42-
ExecuteChildContentAsync = executeChildContentAsync;
43-
GetChildContentAsync = async () =>
44-
{
45-
if (_childContent == null)
46-
{
47-
startWritingScope();
48-
await executeChildContentAsync();
49-
_childContent = endWritingScope().ToString();
50-
}
51-
52-
return _childContent;
53-
};
45+
_tagHelpers = new List<ITagHelper>();
46+
_executeChildContentAsync = executeChildContentAsync;
47+
_startWritingScope = startWritingScope;
48+
_endWritingScope = endWritingScope;
49+
5450
AllAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
5551
HTMLAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
56-
_tagHelpers = new List<ITagHelper>();
5752
TagName = tagName;
5853
}
5954

60-
/// <summary>
61-
/// A delegate used to execute the child content asynchronously.
62-
/// </summary>
63-
public Func<Task> ExecuteChildContentAsync { get; }
64-
65-
/// <summary>
66-
/// A delegate used to execute and retrieve the rendered child content asynchronously.
67-
/// </summary>
68-
/// <remarks>
69-
/// Child content is only executed once. Successive calls to this delegate return a cached result.
70-
/// </remarks>
71-
public Func<Task<string>> GetChildContentAsync { get; }
72-
7355
/// <summary>
7456
/// Indicates if <see cref="GetChildContentAsync"/> has been called.
7557
/// </summary>
@@ -141,5 +123,33 @@ public void AddTagHelperAttribute([NotNull] string name, object value)
141123
{
142124
AllAttributes.Add(name, value);
143125
}
126+
127+
/// <summary>
128+
/// Executes the child content asynchronously.
129+
/// </summary>
130+
/// <returns>A task that indicates when child content execution has completed.</returns>
131+
public Task ExecuteChildContentAsync()
132+
{
133+
return _executeChildContentAsync();
134+
}
135+
136+
/// <summary>
137+
/// Execute and retrieve the rendered child content asynchronously.
138+
/// </summary>
139+
/// <returns>The rendered child content.</returns>
140+
/// <remarks>
141+
/// Child content is only executed once. Successive calls to this method return a cached result.
142+
/// </remarks>
143+
public async Task<string> GetChildContentAsync()
144+
{
145+
if (_childContent == null)
146+
{
147+
_startWritingScope();
148+
await _executeChildContentAsync();
149+
_childContent = _endWritingScope().ToString();
150+
}
151+
152+
return _childContent;
153+
}
144154
}
145155
}

src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CSharp/CSharpTagHelperCodeRenderer.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,8 @@ private void RenderTagHelperContent()
320320
.Write(_tagHelperContext.OutputContentSetPropertyName)
321321
.WriteLine(")");
322322

323+
// Render the body of the if statement, at this point in the codegen the TagHelperOutput's Content was set
324+
// so we should just render its Content, no need to forcefully execute the child content.
323325
using (_writer.BuildScope())
324326
{
325327
RenderTagOutput(_tagHelperContext.OutputGenerateContentMethodName);
@@ -331,29 +333,33 @@ private void RenderTagHelperContent()
331333
.Write(_tagHelperContext.ExecutionContextChildContentRetrievedPropertyName)
332334
.WriteLine(")");
333335

336+
// Render the body of the else if statement, at this point in the codegen the GetChildContentAsync method
337+
// was invoked but the TagHelperOutput's Content was not set. Call into GetChildContentAsync to retrieve
338+
// the cached value of the content so we don't execute the child content twice.
334339
using (_writer.BuildScope())
335340
{
336341
CSharpCodeVisitor.RenderPreWriteStart(_writer, _context);
337342

338-
_writer.Write(ExecutionContextVariableName)
339-
.Write(".")
340-
.Write(_tagHelperContext.ExecutionContextOutputPropertyName)
341-
.Write(".")
342-
.WriteMethodInvocation(_tagHelperContext.ExecutionContextGetChildContentAsyncMethodName,
343-
endLine: false)
344-
.Write(".Result")
343+
_writer.WriteInstanceMethodInvocation(ExecutionContextVariableName,
344+
_tagHelperContext.ExecutionContextGetChildContentAsyncMethodName,
345+
endLine: false);
346+
347+
_writer.Write(".Result")
345348
.WriteEndMethodInvocation();
346349
}
347350

348351
_writer.WriteLine("else");
349352

353+
// Render the body of the else statement, at this point in the codegen the GetChildContentAsync method
354+
// was not invoked and the TagHelperOutput's Content was not set. Call into ExecuteChildContentAsync to
355+
// to execute and render child content.
350356
using (_writer.BuildScope())
351357
{
352358
_writer.WriteInstanceMethodInvocation(
353359
ExecutionContextVariableName,
354360
_tagHelperContext.ExecutionContextExecuteChildContentAsyncMethodName,
355361
endLine: false);
356-
_writer.WriteLine(".Result;");
362+
_writer.WriteLine(".Wait();");
357363
}
358364
}
359365

test/Microsoft.AspNet.Razor.Test/Generator/CSharpTagHelperRenderingTest.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ private static IEnumerable<TagHelperDescriptor> PAndInputTagHelperDescriptors
4646
}
4747
}
4848

49-
}
50-
5149
public static TheoryData TagHelperDescriptorFlowTestData
5250
{
5351
get
@@ -93,13 +91,6 @@ public static TheoryData TagHelperDescriptorFlowTestData
9391
Enumerable.Empty<TagHelperDescriptor>(),
9492
false
9593
},
96-
{
97-
"ContentBehaviorTagHelpers",
98-
"ContentBehaviorTagHelpers",
99-
ContentBehaviorTagHelperDescriptors,
100-
ContentBehaviorTagHelperDescriptors,
101-
false
102-
},
10394
{
10495
"ComplexTagHelpers",
10596
"ComplexTagHelpers",
@@ -128,7 +119,7 @@ public void TagHelpers_RenderingOutputFlowsFoundTagHelperDescriptors(
128119
bool designTimeMode)
129120
{
130121
RunTagHelperTest(
131-
testName,
122+
testName,
132123
baseLineName: baselineName,
133124
tagHelperDescriptors: tagHelperDescriptors,
134125
onResults: (results) =>
@@ -138,6 +129,8 @@ public void TagHelpers_RenderingOutputFlowsFoundTagHelperDescriptors(
138129
TagHelperDescriptorComparer.Default);
139130
},
140131
designTimeMode: designTimeMode);
132+
}
133+
141134
public static TheoryData DesignTimeTagHelperTestData
142135
{
143136
get

test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/CS/Output/BasicTagHelpers.CustomAttributeCodeGenerator.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ public override async Task ExecuteAsync()
4343
}
4444
else if (__tagHelperExecutionContext.ChildContentRetrieved)
4545
{
46-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
46+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
4747
}
4848
else
4949
{
50-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
50+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
5151
}
5252
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
5353
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
@@ -74,11 +74,11 @@ public override async Task ExecuteAsync()
7474
}
7575
else if (__tagHelperExecutionContext.ChildContentRetrieved)
7676
{
77-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
77+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
7878
}
7979
else
8080
{
81-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
81+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
8282
}
8383
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
8484
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
@@ -107,11 +107,11 @@ public override async Task ExecuteAsync()
107107
}
108108
else if (__tagHelperExecutionContext.ChildContentRetrieved)
109109
{
110-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
110+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
111111
}
112112
else
113113
{
114-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
114+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
115115
}
116116
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
117117
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
@@ -133,11 +133,11 @@ public override async Task ExecuteAsync()
133133
}
134134
else if (__tagHelperExecutionContext.ChildContentRetrieved)
135135
{
136-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
136+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
137137
}
138138
else
139139
{
140-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
140+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
141141
}
142142
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
143143
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());

test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/CS/Output/BasicTagHelpers.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ public override async Task ExecuteAsync()
4444
}
4545
else if (__tagHelperExecutionContext.ChildContentRetrieved)
4646
{
47-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
47+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
4848
}
4949
else
5050
{
51-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
51+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
5252
}
5353
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
5454
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
@@ -75,11 +75,11 @@ public override async Task ExecuteAsync()
7575
}
7676
else if (__tagHelperExecutionContext.ChildContentRetrieved)
7777
{
78-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
78+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
7979
}
8080
else
8181
{
82-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
82+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
8383
}
8484
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
8585
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
@@ -108,11 +108,11 @@ public override async Task ExecuteAsync()
108108
}
109109
else if (__tagHelperExecutionContext.ChildContentRetrieved)
110110
{
111-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
111+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
112112
}
113113
else
114114
{
115-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
115+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
116116
}
117117
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
118118
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
@@ -134,11 +134,11 @@ public override async Task ExecuteAsync()
134134
}
135135
else if (__tagHelperExecutionContext.ChildContentRetrieved)
136136
{
137-
WriteLiteral(__tagHelperExecutionContext.Output.GetChildContentAsync().Result);
137+
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
138138
}
139139
else
140140
{
141-
__tagHelperExecutionContext.ExecuteChildContentAsync().Result;
141+
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
142142
}
143143
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
144144
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());

0 commit comments

Comments
 (0)