diff --git a/src/Microsoft.AspNet.Mvc.Razor/IRazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/IRazorPage.cs
index 57e57b3166..a647e22641 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/IRazorPage.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/IRazorPage.cs
@@ -1,10 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using System;
using System.Collections.Generic;
-using System.IO;
using System.Threading.Tasks;
+using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc.Razor
@@ -20,9 +19,9 @@ namespace Microsoft.AspNet.Mvc.Razor
ViewContext ViewContext { get; set; }
///
- /// Gets or sets the action invoked to render the body.
+ /// Gets or sets the body content.
///
- Func RenderBodyDelegateAsync { get; set; }
+ IHtmlContent BodyContent { get; set; }
///
/// Gets or sets a flag that determines if the layout of this page is being rendered.
@@ -64,7 +63,7 @@ namespace Microsoft.AspNet.Mvc.Razor
/// Verifies that all sections defined in were rendered, or
/// the body was rendered if no sections were defined.
///
- /// if one or more sections were not rendered or if no sections were
+ /// if one or more sections were not rendered or if no sections were
/// defined and the body was not rendered.
void EnsureRenderedBodyOrSections();
}
diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs
index 27b0c8b620..f730a171c8 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs
@@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Mvc.Razor
public ITempDataDictionary TempData => ViewContext?.TempData;
///
- public Func RenderBodyDelegateAsync { get; set; }
+ public IHtmlContent BodyContent { get; set; }
///
public bool IsLayoutBeingRendered { get; set; }
@@ -249,26 +249,26 @@ namespace Microsoft.AspNet.Mvc.Razor
_originalWriter = null;
}
- var tagHelperContentWrapperTextWriter = new TagHelperContentWrapperTextWriter(Output.Encoding);
+ var tagHelperContent = new DefaultTagHelperContent();
var razorWriter = writer as RazorTextWriter;
if (razorWriter != null)
{
- razorWriter.CopyTo(tagHelperContentWrapperTextWriter);
+ tagHelperContent.Append(razorWriter.Buffer);
}
else
{
var stringCollectionTextWriter = writer as StringCollectionTextWriter;
if (stringCollectionTextWriter != null)
{
- stringCollectionTextWriter.CopyTo(tagHelperContentWrapperTextWriter, HtmlEncoder);
+ tagHelperContent.Append(stringCollectionTextWriter.Content);
}
else
{
- tagHelperContentWrapperTextWriter.Write(writer.ToString());
+ tagHelperContent.AppendHtml(writer.ToString());
}
}
- return tagHelperContentWrapperTextWriter.Content;
+ return tagHelperContent;
}
///
@@ -669,16 +669,16 @@ namespace Microsoft.AspNet.Mvc.Razor
/// In a Razor layout page, renders the portion of a content page that is not within a named section.
///
/// The HTML content to render.
- protected virtual HelperResult RenderBody()
+ protected virtual IHtmlContent RenderBody()
{
- if (RenderBodyDelegateAsync == null)
+ if (BodyContent == null)
{
var message = Resources.FormatRazorPage_MethodCannotBeCalled(nameof(RenderBody), Path);
throw new InvalidOperationException(message);
}
_renderedBody = true;
- return new HelperResult(RenderBodyDelegateAsync);
+ return BodyContent;
}
///
@@ -886,7 +886,7 @@ namespace Microsoft.AspNet.Mvc.Razor
throw new InvalidOperationException(Resources.FormatSectionsNotRendered(Path, sectionNames));
}
}
- else if (RenderBodyDelegateAsync != null && !_renderedBody)
+ else if (BodyContent != null && !_renderedBody)
{
// There are no sections defined, but RenderBody was NOT called.
// If a body was defined, then RenderBody should have been called.
diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorTextWriter.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorTextWriter.cs
index 6cae8bb1ae..87a2fd57bc 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/RazorTextWriter.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/RazorTextWriter.cs
@@ -48,6 +48,11 @@ namespace Microsoft.AspNet.Mvc.Razor
///
public bool IsBuffering { get; private set; } = true;
+ ///
+ /// Gets the buffered content.
+ ///
+ public IHtmlContent Buffer => BufferedWriter.Content;
+
// Internal for unit testing
internal StringCollectionTextWriter BufferedWriter { get; }
@@ -185,7 +190,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
IsBuffering = false;
TargetWriter = UnbufferedWriter;
- CopyTo(UnbufferedWriter);
+ Buffer.WriteTo(UnbufferedWriter, HtmlEncoder);
}
UnbufferedWriter.Flush();
@@ -197,43 +202,16 @@ namespace Microsoft.AspNet.Mvc.Razor
/// to the unbuffered writer.
///
/// A that represents the asynchronous copy and flush operations.
- public override async Task FlushAsync()
+ public override Task FlushAsync()
{
if (IsBuffering)
{
IsBuffering = false;
TargetWriter = UnbufferedWriter;
- await CopyToAsync(UnbufferedWriter);
+ Buffer.WriteTo(UnbufferedWriter, HtmlEncoder);
}
- await UnbufferedWriter.FlushAsync();
- }
-
- ///
- public void CopyTo(TextWriter writer)
- {
- writer = UnWrapRazorTextWriter(writer);
- BufferedWriter.CopyTo(writer, HtmlEncoder);
- }
-
- ///
- public Task CopyToAsync(TextWriter writer)
- {
- writer = UnWrapRazorTextWriter(writer);
- return BufferedWriter.CopyToAsync(writer, HtmlEncoder);
- }
-
- private static TextWriter UnWrapRazorTextWriter(TextWriter writer)
- {
- var targetRazorTextWriter = writer as RazorTextWriter;
- if (targetRazorTextWriter != null)
- {
- writer = targetRazorTextWriter.IsBuffering ?
- targetRazorTextWriter.BufferedWriter :
- targetRazorTextWriter.UnbufferedWriter;
- }
-
- return writer;
+ return UnbufferedWriter.FlushAsync();
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs
index 46f2950740..6975a45b83 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs
@@ -203,7 +203,7 @@ namespace Microsoft.AspNet.Mvc.Razor
// in the layout.
previousPage.IsLayoutBeingRendered = true;
layoutPage.PreviousSectionWriters = previousPage.SectionWriters;
- layoutPage.RenderBodyDelegateAsync = bodyWriter.CopyToAsync;
+ layoutPage.BodyContent = bodyWriter.Buffer;
bodyWriter = await RenderPageAsync(layoutPage, context, viewStartPages: null);
renderedLayouts.Add(layoutPage);
@@ -219,7 +219,7 @@ namespace Microsoft.AspNet.Mvc.Razor
if (bodyWriter.IsBuffering)
{
// Only copy buffered content to the Output if we're currently buffering.
- await bodyWriter.CopyToAsync(context.Writer);
+ bodyWriter.Buffer.WriteTo(context.Writer, _htmlEncoder);
}
}
diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs
index c1bde016d8..90361d1a56 100644
--- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs
@@ -28,7 +28,7 @@ namespace Microsoft.AspNet.Mvc.Razor
public class RazorPageTest
{
private readonly RenderAsyncDelegate _nullRenderAsyncDelegate = writer => Task.FromResult(0);
- private readonly Func NullAsyncWrite = CreateAsyncWriteDelegate(string.Empty);
+ private readonly Func NullAsyncWrite = writer => writer.WriteAsync(string.Empty);
[Fact]
public async Task WritingScopesRedirectContentWrittenToViewContextWriter()
@@ -311,7 +311,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
{ "baz", _nullRenderAsyncDelegate }
};
- page.RenderBodyDelegateAsync = CreateAsyncWriteDelegate("body-content");
+ page.BodyContent = new HtmlString("body-content");
// Act
await page.ExecuteAsync();
@@ -335,7 +335,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
{ "baz", _nullRenderAsyncDelegate }
};
- page.RenderBodyDelegateAsync = CreateAsyncWriteDelegate("body-content");
+ page.BodyContent = new HtmlString("body-content");
// Act
await page.ExecuteAsync();
@@ -444,7 +444,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
});
page.Path = path;
- page.RenderBodyDelegateAsync = CreateAsyncWriteDelegate("some content");
+ page.BodyContent = new HtmlString("some content");
// Act
await page.ExecuteAsync();
@@ -464,7 +464,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
});
page.Path = path;
- page.RenderBodyDelegateAsync = CreateAsyncWriteDelegate("some content");
+ page.BodyContent = new HtmlString("some content");
page.PreviousSectionWriters = new Dictionary
{
{ sectionName, _nullRenderAsyncDelegate }
@@ -490,7 +490,7 @@ namespace Microsoft.AspNet.Mvc.Razor
v.RenderSection(sectionA);
v.RenderSection(sectionB);
});
- page.RenderBodyDelegateAsync = CreateAsyncWriteDelegate("some content");
+ page.BodyContent = new HtmlString("some content");
page.PreviousSectionWriters = new Dictionary
{
{ sectionA, _nullRenderAsyncDelegate },
@@ -524,7 +524,7 @@ namespace Microsoft.AspNet.Mvc.Razor
v.Write(v.RenderSection("footer"));
v.WriteLiteral("Layout end");
});
- page.RenderBodyDelegateAsync = CreateAsyncWriteDelegate("body content" + Environment.NewLine);
+ page.BodyContent = new HtmlString("body content" + Environment.NewLine);
page.PreviousSectionWriters = new Dictionary
{
{
@@ -1181,11 +1181,6 @@ namespace Microsoft.AspNet.Mvc.Razor
new HtmlHelperOptions());
}
- private static Func CreateAsyncWriteDelegate(string value)
- {
- return async (writer) => await writer.WriteAsync(value);
- }
-
public abstract class TestableRazorPage : RazorPage
{
public TestableRazorPage()
@@ -1202,7 +1197,7 @@ namespace Microsoft.AspNet.Mvc.Razor
}
}
- public HelperResult RenderBodyPublic()
+ public IHtmlContent RenderBodyPublic()
{
return base.RenderBody();
}
diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorTextWriterTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorTextWriterTest.cs
index ded9882149..21c9be6ff2 100644
--- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorTextWriterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorTextWriterTest.cs
@@ -283,123 +283,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
Assert.Equal("Hello, world!", stringWriter.ToString());
}
- [Fact]
- public void Copy_CopiesContent_IfTargetTextWriterIsARazorTextWriterAndBuffering()
- {
- // Arrange
- var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
- var target = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
-
- // Act
- source.Write("Hello world");
- source.Write(new char[1], 0, 1);
- source.CopyTo(target);
-
- // Assert
- // Make sure content was written to the source.
- Assert.Equal(2, source.BufferedWriter.Entries.Count);
- Assert.Equal(1, target.BufferedWriter.Entries.Count);
- Assert.Same(source.BufferedWriter.Content, Assert.Single(target.BufferedWriter.Entries));
- }
-
- [Fact]
- public void Copy_CopiesContent_IfTargetTextWriterIsARazorTextWriterAndNotBuffering()
- {
- // Arrange
- var unbufferedWriter = new Mock();
- var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
- var target = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new HtmlTestEncoder());
-
- // Act
- target.Flush();
- source.Write("Hello world");
- source.Write(new[] { 'a', 'b', 'c', 'd' }, 1, 2);
- source.CopyTo(target);
-
- // Assert
- // Make sure content was written to the source.
- Assert.Equal(2, source.BufferedWriter.Entries.Count);
- Assert.Empty(target.BufferedWriter.Entries);
- unbufferedWriter.Verify(v => v.Write("Hello world"), Times.Once());
- unbufferedWriter.Verify(v => v.Write("bc"), Times.Once());
- }
-
- [Fact]
- public void Copy_WritesContent_IfTargetTextWriterIsNotARazorTextWriter()
- {
- // Arrange
- var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
- var target = new StringWriter();
- var expected = "Hello world" + Environment.NewLine + "abc";
-
- // Act
- source.WriteLine("Hello world");
- source.Write(new[] { 'x', 'a', 'b', 'c' }, 1, 3);
- source.CopyTo(target);
-
- // Assert
- Assert.Equal(expected, target.ToString());
- }
-
- [Fact]
- public async Task CopyAsync_WritesContent_IfTargetTextWriterIsARazorTextWriterAndBuffering()
- {
- // Arrange
- var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
- var target = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
-
- // Act
- source.WriteLine("Hello world");
- source.Write(new[] { 'x', 'a', 'b', 'c' }, 1, 3);
- await source.CopyToAsync(target);
-
- // Assert
- Assert.Equal(3, source.BufferedWriter.Entries.Count);
- Assert.Equal(1, target.BufferedWriter.Entries.Count);
- Assert.Equal(source.BufferedWriter.Content, Assert.Single(target.BufferedWriter.Entries));
- }
-
- //[Fact]
- // IHtmlContent currently does not support async writes. Hence disabling this test.
- public async Task CopyAsync_WritesContent_IfTargetTextWriterIsARazorTextWriterAndNotBuffering()
- {
- // Arrange
- var unbufferedWriter = new Mock();
- var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
- var target = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new HtmlTestEncoder());
-
- // Act
- await target.FlushAsync();
- source.WriteLine("Hello from Asp.Net");
- await source.WriteAsync(new[] { 'x', 'y', 'z', 'u' }, 0, 3);
- await source.CopyToAsync(target);
-
- // Assert
- // Make sure content was written to the source.
- Assert.Equal(3, source.BufferedWriter.Entries.Count);
- Assert.Empty(target.BufferedWriter.Content.ToString());
- unbufferedWriter.Verify(v => v.WriteAsync("Hello from Asp.Net"), Times.Once());
- unbufferedWriter.Verify(v => v.WriteAsync(Environment.NewLine), Times.Once());
- unbufferedWriter.Verify(v => v.WriteAsync("xyz"), Times.Once());
- }
-
- [Fact]
- public async Task CopyAsync_WritesContent_IfTargetTextWriterIsNotARazorTextWriter()
- {
- // Arrange
- var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new HtmlTestEncoder());
- var target = new StringWriter();
- var expected = "Hello world" + Environment.NewLine;
-
- // Act
- source.Write("Hello ");
- await source.WriteLineAsync(new[] { 'w', 'o', 'r', 'l', 'd' });
- await source.CopyToAsync(target);
-
- // Assert
- Assert.Equal(expected, target.ToString());
- }
-
private class TestClass
{
public override string ToString()