RenderSection \ RenderSectionAsync does not work in sections
Fixes #1509
This commit is contained in:
parent
dd1500dcfb
commit
052ad3e95f
|
|
@ -451,7 +451,11 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
/// In layout pages, renders the content of the section named <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the section to render.</param>
|
||||
/// <returns>Returns a HtmlString that contains the rendered HTML.</returns>
|
||||
/// <returns>Returns <see cref="HtmlString.Empty"/> to allow the <see cref="Write(object)"/> call to
|
||||
/// succeed.</returns>
|
||||
/// <remarks>The method writes to the <see cref="Output"/> 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.</remarks>
|
||||
public HtmlString RenderSection([NotNull] string name)
|
||||
{
|
||||
return RenderSection(name, required: true);
|
||||
|
|
@ -462,7 +466,11 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
/// </summary>
|
||||
/// <param name="name">The section to render.</param>
|
||||
/// <param name="required">Indicates if this section must be rendered.</param>
|
||||
/// <returns>Returns a HtmlString that contains the rendered HTML.</returns>
|
||||
/// <returns>Returns <see cref="HtmlString.Empty"/> to allow the <see cref="Write(object)"/> call to
|
||||
/// succeed.</returns>
|
||||
/// <remarks>The method writes to the <see cref="Output"/> 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.</remarks>
|
||||
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 <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The section to render.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that on completion returns a <see cref="HtmlString"/> containing
|
||||
/// the rendered HTML.</returns>
|
||||
/// <returns>A <see cref="Task{HtmlString}"/> that on completion returns <see cref="HtmlString.Empty"/> that
|
||||
/// allows the <see cref="Write(object)"/> call to succeed.</returns>
|
||||
/// <remarks>The method writes to the <see cref="Output"/> 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.</remarks>
|
||||
public Task<HtmlString> 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 <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The section to render.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that on completion returns a <see cref="HtmlString"/> containing
|
||||
/// the rendered HTML.</returns>
|
||||
/// <returns>A <see cref="Task{HtmlString}"/> that on completion returns <see cref="HtmlString.Empty"/> that
|
||||
/// allows the <see cref="Write(object)"/> call to succeed.</returns>
|
||||
/// <remarks>The method writes to the <see cref="Output"/> 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.</remarks>
|
||||
/// <exception cref="InvalidOperationException">if <paramref name="required"/> is <c>true</c> and the section
|
||||
/// was not registered using the <c>@section</c> in the Razor page.</exception>
|
||||
public async Task<HtmlString> 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
@"<title>Page With Components and Partials</title>
|
||||
|
||||
RenderBody content", GetTrimmedString(stream));
|
||||
Assert.Equal(string.Join(Environment.NewLine,
|
||||
"<title>" + title + "</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",
|
||||
"<p>section-content</p>"), GetTrimmedString(stream));
|
||||
waitService.WaitForServer();
|
||||
|
||||
// Assert - 3
|
||||
Assert.Equal(
|
||||
@"component-content
|
||||
<span>Content that takes time to produce</span>", GetTrimmedString(stream));
|
||||
Assert.Equal(string.Join(
|
||||
Environment.NewLine,
|
||||
"component-content",
|
||||
" <span>Content that takes time to produce</span>",
|
||||
"",
|
||||
"More content from layout"), GetTrimmedString(stream));
|
||||
}
|
||||
|
||||
private IServiceProvider GetServiceProvider(WaitService waitService)
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<string> GetValueAsync()
|
||||
{
|
||||
await Task.Delay(100);
|
||||
return "Value from TaskReturningString";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ namespace RazorWebSite
|
|||
// Add MVC services to the services container
|
||||
services.AddMvc(configuration);
|
||||
services.AddTransient<InjectedHelper>();
|
||||
services.AddTransient<TaskReturningService>();
|
||||
services.Configure<RazorViewEngineOptions>(options =>
|
||||
{
|
||||
var expander = new LanguageViewLocationExpander(
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
<p>section-content</p>
|
||||
@{
|
||||
await FlushAsync();
|
||||
WaitService.WaitForClient();
|
||||
}
|
||||
@await Component.InvokeAsync("ComponentThatSetsTitle")
|
||||
<span>Content that takes time to produce</span>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
<p>section-content</p>
|
||||
@{
|
||||
await FlushAsync();
|
||||
WaitService.WaitForClient();
|
||||
}
|
||||
@await Component.InvokeAsync("ComponentThatSetsTitle")
|
||||
<span>Content that takes time to produce</span>
|
||||
}
|
||||
|
|
@ -6,6 +6,3 @@
|
|||
}
|
||||
@RenderBody()
|
||||
@await RenderSectionAsync("content")
|
||||
@{
|
||||
WaitService.NotifyClient();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,4 @@
|
|||
}
|
||||
@await Html.PartialAsync("_PartialThatSetsTitle")
|
||||
@await RenderSectionAsync("content")
|
||||
@{
|
||||
WaitService.NotifyClient();
|
||||
}
|
||||
More content from layout
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
@inject WaitService WaitService
|
||||
<title>@ViewBag.Title</title>
|
||||
@RenderBody()
|
||||
@{
|
||||
await FlushAsync();
|
||||
WaitService.WaitForClient();
|
||||
}
|
||||
@await Html.PartialAsync("_PartialThatSetsTitle")
|
||||
@await RenderSectionAsync("content")
|
||||
More content from layout
|
||||
Loading…
Reference in New Issue