diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs
index 2db0e165da..870503d01b 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs
@@ -451,7 +451,11 @@ namespace Microsoft.AspNet.Mvc.Razor
/// In layout pages, renders the content of the section named .
///
/// The name of the section to render.
- /// Returns a HtmlString that contains the rendered HTML.
+ /// Returns to allow the call to
+ /// succeed.
+ /// The method writes to the and the value returned is a token
+ /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
+ /// value does not represent the rendered content.
public HtmlString RenderSection([NotNull] string name)
{
return RenderSection(name, required: true);
@@ -462,7 +466,11 @@ namespace Microsoft.AspNet.Mvc.Razor
///
/// The section to render.
/// Indicates if this section must be rendered.
- /// Returns a HtmlString that contains the rendered HTML.
+ /// Returns to allow the call to
+ /// succeed.
+ /// The method writes to the and the value returned is a token
+ /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
+ /// value does not represent the rendered content.
public HtmlString RenderSection([NotNull] string name, bool required)
{
EnsureMethodCanBeInvoked(nameof(RenderSection));
@@ -475,8 +483,11 @@ namespace Microsoft.AspNet.Mvc.Razor
/// In layout pages, asynchronously renders the content of the section named .
///
/// The section to render.
- /// A that on completion returns a containing
- /// the rendered HTML.
+ /// A that on completion returns that
+ /// allows the call to succeed.
+ /// The method writes to the and the value returned is a token
+ /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
+ /// value does not represent the rendered content.
public Task RenderSectionAsync([NotNull] string name)
{
return RenderSectionAsync(name, required: true);
@@ -486,8 +497,11 @@ namespace Microsoft.AspNet.Mvc.Razor
/// In layout pages, asynchronously renders the content of the section named .
///
/// The section to render.
- /// A that on completion returns a containing
- /// the rendered HTML.
+ /// A that on completion returns that
+ /// allows the call to succeed.
+ /// The method writes to the and the value returned is a token
+ /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
+ /// value does not represent the rendered content.
/// if is true and the section
/// was not registered using the @section in the Razor page.
public async Task RenderSectionAsync([NotNull] string name, bool required)
@@ -508,14 +522,11 @@ namespace Microsoft.AspNet.Mvc.Razor
if (PreviousSectionWriters.TryGetValue(sectionName, out renderDelegate))
{
_renderedSections.Add(sectionName);
+ await renderDelegate(Output);
- using (var writer = new StringCollectionTextWriter(Output.Encoding))
- {
- await renderDelegate(writer);
-
- // Returning a disposed StringCollectionTextWriter is safe.
- return new HtmlString(writer);
- }
+ // Return a token value that allows the Write call that wraps the RenderSection \ RenderSectionAsync
+ // to succeed.
+ return HtmlString.Empty;
}
else if (required)
{
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs
index 00410ab04c..27f3315c91 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs
@@ -67,8 +67,10 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal("Final content", GetTrimmedString(stream));
}
- [Fact]
- public async Task FlushPointsAreExecutedForPagesWithComponentsAndPartials()
+ [Theory]
+ [InlineData("PageWithPartialsAndViewComponents", "FlushAsync invoked inside RenderSection")]
+ [InlineData("PageWithRenderSectionAsync", "FlushAsync invoked inside RenderSectionAsync")]
+ public async Task FlushPointsAreExecutedForPagesWithComponentsPartialsAndSections(string action, string title)
{
var waitService = new WaitService();
var serviceProvider = GetServiceProvider(waitService);
@@ -77,23 +79,31 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
var client = server.CreateClient();
// Act
- var stream = await client.GetStreamAsync("http://localhost/FlushPoint/PageWithPartialsAndViewComponents");
+ var stream = await client.GetStreamAsync("http://localhost/FlushPoint/" + action);
// Assert - 1
- Assert.Equal(
-@"Page With Components and Partials
-
-RenderBody content", GetTrimmedString(stream));
+ Assert.Equal(string.Join(Environment.NewLine,
+ "" + title + "",
+ "",
+ "RenderBody content"), GetTrimmedString(stream));
waitService.WaitForServer();
// Assert - 2
- Assert.Equal("partial-content", GetTrimmedString(stream));
+ Assert.Equal(string.Join(
+ Environment.NewLine,
+ "partial-content",
+ "",
+ "Value from TaskReturningString",
+ "section-content
"), GetTrimmedString(stream));
waitService.WaitForServer();
// Assert - 3
- Assert.Equal(
-@"component-content
- Content that takes time to produce", GetTrimmedString(stream));
+ Assert.Equal(string.Join(
+ Environment.NewLine,
+ "component-content",
+ " Content that takes time to produce",
+ "",
+ "More content from layout"), GetTrimmedString(stream));
}
private IServiceProvider GetServiceProvider(WaitService waitService)
diff --git a/test/WebSites/RazorWebSite/Controllers/FlushPoint.cs b/test/WebSites/RazorWebSite/Controllers/FlushPoint.cs
index 021ca21a6f..f8f47ebb23 100644
--- a/test/WebSites/RazorWebSite/Controllers/FlushPoint.cs
+++ b/test/WebSites/RazorWebSite/Controllers/FlushPoint.cs
@@ -17,9 +17,16 @@ namespace RazorWebSite
return View();
}
+ // This uses RenderSection to render the section that contains a FlushAsync call
public ViewResult PageWithPartialsAndViewComponents()
{
return View();
}
+
+ // This uses RenderSectionAsync to render the section that contains a FlushAsync call
+ public ViewResult PageWithRenderSectionAsync()
+ {
+ return View("PageWithSectionInvokedViaRenderSectionAsync");
+ }
}
}
\ No newline at end of file
diff --git a/test/WebSites/RazorWebSite/Services/TaskReturningService.cs b/test/WebSites/RazorWebSite/Services/TaskReturningService.cs
new file mode 100644
index 0000000000..fc68ea6573
--- /dev/null
+++ b/test/WebSites/RazorWebSite/Services/TaskReturningService.cs
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Threading.Tasks;
+
+namespace RazorWebSite
+{
+ public class TaskReturningService
+ {
+ public async Task GetValueAsync()
+ {
+ await Task.Delay(100);
+ return "Value from TaskReturningString";
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/RazorWebSite/Startup.cs b/test/WebSites/RazorWebSite/Startup.cs
index 51cbc1681c..14086728dc 100644
--- a/test/WebSites/RazorWebSite/Startup.cs
+++ b/test/WebSites/RazorWebSite/Startup.cs
@@ -17,6 +17,7 @@ namespace RazorWebSite
// Add MVC services to the services container
services.AddMvc(configuration);
services.AddTransient();
+ services.AddTransient();
services.Configure(options =>
{
var expander = new LanguageViewLocationExpander(
diff --git a/test/WebSites/RazorWebSite/Views/FlushPoint/PageWithPartialsAndViewComponents.cshtml b/test/WebSites/RazorWebSite/Views/FlushPoint/PageWithPartialsAndViewComponents.cshtml
index d83f5a82d2..0b979014f9 100644
--- a/test/WebSites/RazorWebSite/Views/FlushPoint/PageWithPartialsAndViewComponents.cshtml
+++ b/test/WebSites/RazorWebSite/Views/FlushPoint/PageWithPartialsAndViewComponents.cshtml
@@ -1,15 +1,19 @@
@inject WaitService WaitService
+@inject TaskReturningService TaskReturningService
+
@{
Layout = "/Views/Shared/_LayoutWithPartialAndFlush.cshtml";
- ViewBag.Title = "Page With Components and Partials";
+ ViewBag.Title = "FlushAsync invoked inside RenderSection";
}
RenderBody content
@section content
{
+@await TaskReturningService.GetValueAsync()
+section-content
@{
await FlushAsync();
WaitService.WaitForClient();
}
@await Component.InvokeAsync("ComponentThatSetsTitle")
Content that takes time to produce
-}
\ No newline at end of file
+}
diff --git a/test/WebSites/RazorWebSite/Views/FlushPoint/PageWithSectionInvokedViaRenderSectionAsync.cshtml b/test/WebSites/RazorWebSite/Views/FlushPoint/PageWithSectionInvokedViaRenderSectionAsync.cshtml
new file mode 100644
index 0000000000..660e934810
--- /dev/null
+++ b/test/WebSites/RazorWebSite/Views/FlushPoint/PageWithSectionInvokedViaRenderSectionAsync.cshtml
@@ -0,0 +1,19 @@
+@inject WaitService WaitService
+@inject TaskReturningService TaskReturningService
+
+@{
+ Layout = "/Views/Shared/_LayoutWithRenderSectionAsync.cshtml";
+ ViewBag.Title = "FlushAsync invoked inside RenderSectionAsync";
+}
+RenderBody content
+@section content
+{
+@await TaskReturningService.GetValueAsync()
+section-content
+ @{
+ await FlushAsync();
+ WaitService.WaitForClient();
+ }
+ @await Component.InvokeAsync("ComponentThatSetsTitle")
+ Content that takes time to produce
+}
diff --git a/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithFlush.cshtml b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithFlush.cshtml
index cb3d3ba7e1..646d08f7bb 100644
--- a/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithFlush.cshtml
+++ b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithFlush.cshtml
@@ -6,6 +6,3 @@
}
@RenderBody()
@await RenderSectionAsync("content")
-@{
- WaitService.NotifyClient();
-}
diff --git a/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithPartialAndFlush.cshtml b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithPartialAndFlush.cshtml
index 090234c40f..8dfc88f054 100644
--- a/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithPartialAndFlush.cshtml
+++ b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithPartialAndFlush.cshtml
@@ -7,6 +7,4 @@
}
@await Html.PartialAsync("_PartialThatSetsTitle")
@await RenderSectionAsync("content")
-@{
- WaitService.NotifyClient();
-}
+More content from layout
diff --git a/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithRenderSectionAsync.cshtml b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithRenderSectionAsync.cshtml
new file mode 100644
index 0000000000..8dfc88f054
--- /dev/null
+++ b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithRenderSectionAsync.cshtml
@@ -0,0 +1,10 @@
+@inject WaitService WaitService
+@ViewBag.Title
+@RenderBody()
+@{
+ await FlushAsync();
+ WaitService.WaitForClient();
+}
+@await Html.PartialAsync("_PartialThatSetsTitle")
+@await RenderSectionAsync("content")
+More content from layout