React to BufferedHtmlContent changes

This commit is contained in:
Ryan Nowak 2015-09-12 21:41:06 -07:00
parent 85bb33a62a
commit 94388a8804
29 changed files with 283 additions and 168 deletions

View File

@ -271,9 +271,7 @@ Global
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.ActiveCfg = Release|Any CPU {4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.ActiveCfg = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.Build.0 = Release|Any CPU {4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.Build.0 = Release|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.ActiveCfg = Debug|Any CPU {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.ActiveCfg = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.Build.0 = Debug|Any CPU {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.Build.0 = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Any CPU.ActiveCfg = Release|Any CPU {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -378,6 +376,7 @@ Global
{F21E225B-190B-4DAA-8B0A-05986D231F56}.Release|x86.ActiveCfg = Release|Any CPU {F21E225B-190B-4DAA-8B0A-05986D231F56}.Release|x86.ActiveCfg = Release|Any CPU
{F21E225B-190B-4DAA-8B0A-05986D231F56}.Release|x86.Build.0 = Release|Any CPU {F21E225B-190B-4DAA-8B0A-05986D231F56}.Release|x86.Build.0 = Release|Any CPU
{3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|x86.ActiveCfg = Debug|Any CPU {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|x86.ActiveCfg = Debug|Any CPU

View File

@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.Razor.Internal; using Microsoft.AspNet.Mvc.Razor.Internal;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
@ -30,9 +32,12 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <param name="unbufferedWriter">The <see cref="TextWriter"/> to write output to when this instance /// <param name="unbufferedWriter">The <see cref="TextWriter"/> to write output to when this instance
/// is no longer buffering.</param> /// is no longer buffering.</param>
/// <param name="encoding">The character <see cref="Encoding"/> in which the output is written.</param> /// <param name="encoding">The character <see cref="Encoding"/> in which the output is written.</param>
public RazorTextWriter(TextWriter unbufferedWriter, Encoding encoding) /// <param name="encoder">The HTML encoder.</param>
public RazorTextWriter(TextWriter unbufferedWriter, Encoding encoding, IHtmlEncoder encoder)
{ {
UnbufferedWriter = unbufferedWriter; UnbufferedWriter = unbufferedWriter;
HtmlEncoder = encoder;
BufferedWriter = new StringCollectionTextWriter(encoding); BufferedWriter = new StringCollectionTextWriter(encoding);
TargetWriter = BufferedWriter; TargetWriter = BufferedWriter;
} }
@ -53,8 +58,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private TextWriter TargetWriter { get; set; } private TextWriter TargetWriter { get; set; }
[RazorInject] private IHtmlEncoder HtmlEncoder { get; }
private IHtmlEncoder HtmlEncoder { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public override void Write(char value) public override void Write(char value)
@ -65,10 +69,10 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <inheritdoc /> /// <inheritdoc />
public override void Write(object value) public override void Write(object value)
{ {
var htmlString = value as HtmlString; var htmlContent = value as IHtmlContent;
if (htmlString != null) if (htmlContent != null)
{ {
htmlString.WriteTo(TargetWriter, HtmlEncoder); htmlContent.WriteTo(TargetWriter, HtmlEncoder);
return; return;
} }

View File

@ -9,6 +9,7 @@ using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PageExecutionInstrumentation; using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
@ -21,6 +22,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private readonly IRazorViewEngine _viewEngine; private readonly IRazorViewEngine _viewEngine;
private readonly IRazorPageActivator _pageActivator; private readonly IRazorPageActivator _pageActivator;
private readonly IViewStartProvider _viewStartProvider; private readonly IViewStartProvider _viewStartProvider;
private readonly IHtmlEncoder _htmlEncoder;
private IPageExecutionListenerFeature _pageExecutionFeature; private IPageExecutionListenerFeature _pageExecutionFeature;
/// <summary> /// <summary>
@ -30,18 +32,21 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <param name="pageActivator">The <see cref="IRazorPageActivator"/> used to activate pages.</param> /// <param name="pageActivator">The <see cref="IRazorPageActivator"/> used to activate pages.</param>
/// <param name="viewStartProvider">The <see cref="IViewStartProvider"/> used for discovery of _ViewStart /// <param name="viewStartProvider">The <see cref="IViewStartProvider"/> used for discovery of _ViewStart
/// <param name="razorPage">The <see cref="IRazorPage"/> instance to execute.</param> /// <param name="razorPage">The <see cref="IRazorPage"/> instance to execute.</param>
/// <param name="htmlEncoder">The HTML encoder.</param>
/// <param name="isPartial">Determines if the view is to be executed as a partial.</param> /// <param name="isPartial">Determines if the view is to be executed as a partial.</param>
/// pages</param> /// pages</param>
public RazorView(IRazorViewEngine viewEngine, public RazorView(IRazorViewEngine viewEngine,
IRazorPageActivator pageActivator, IRazorPageActivator pageActivator,
IViewStartProvider viewStartProvider, IViewStartProvider viewStartProvider,
IRazorPage razorPage, IRazorPage razorPage,
IHtmlEncoder htmlEncoder,
bool isPartial) bool isPartial)
{ {
_viewEngine = viewEngine; _viewEngine = viewEngine;
_pageActivator = pageActivator; _pageActivator = pageActivator;
_viewStartProvider = viewStartProvider; _viewStartProvider = viewStartProvider;
RazorPage = razorPage; RazorPage = razorPage;
_htmlEncoder = htmlEncoder;
IsPartial = isPartial; IsPartial = isPartial;
} }
@ -77,11 +82,12 @@ namespace Microsoft.AspNet.Mvc.Razor
await RenderLayoutAsync(context, bodyWriter); await RenderLayoutAsync(context, bodyWriter);
} }
private async Task<IBufferedTextWriter> RenderPageAsync(IRazorPage page, private async Task<IBufferedTextWriter> RenderPageAsync(
ViewContext context, IRazorPage page,
bool executeViewStart) ViewContext context,
bool executeViewStart)
{ {
var razorTextWriter = new RazorTextWriter(context.Writer, context.Writer.Encoding); var razorTextWriter = new RazorTextWriter(context.Writer, context.Writer.Encoding, _htmlEncoder);
var writer = (TextWriter)razorTextWriter; var writer = (TextWriter)razorTextWriter;
var bufferedWriter = (IBufferedTextWriter)razorTextWriter; var bufferedWriter = (IBufferedTextWriter)razorTextWriter;

View File

@ -3,6 +3,7 @@
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
@ -12,6 +13,7 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary> /// </summary>
public class RazorViewFactory : IRazorViewFactory public class RazorViewFactory : IRazorViewFactory
{ {
private readonly IHtmlEncoder _htmlEncoder;
private readonly IRazorPageActivator _pageActivator; private readonly IRazorPageActivator _pageActivator;
private readonly IViewStartProvider _viewStartProvider; private readonly IViewStartProvider _viewStartProvider;
@ -22,10 +24,12 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <param name="viewStartProvider">The <see cref="IViewStartProvider"/> used for discovery of _ViewStart /// <param name="viewStartProvider">The <see cref="IViewStartProvider"/> used for discovery of _ViewStart
/// pages</param> /// pages</param>
public RazorViewFactory(IRazorPageActivator pageActivator, public RazorViewFactory(IRazorPageActivator pageActivator,
IViewStartProvider viewStartProvider) IViewStartProvider viewStartProvider,
IHtmlEncoder htmlEncoder)
{ {
_pageActivator = pageActivator; _pageActivator = pageActivator;
_viewStartProvider = viewStartProvider; _viewStartProvider = viewStartProvider;
_htmlEncoder = htmlEncoder;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -33,7 +37,13 @@ namespace Microsoft.AspNet.Mvc.Razor
[NotNull] IRazorPage page, [NotNull] IRazorPage page,
bool isPartial) bool isPartial)
{ {
var razorView = new RazorView(viewEngine, _pageActivator, _viewStartProvider, page, isPartial); var razorView = new RazorView(
viewEngine,
_pageActivator,
_viewStartProvider,
page,
_htmlEncoder,
isPartial);
return razorView; return razorView;
} }
} }

View File

@ -44,13 +44,13 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <inheritdoc /> /// <inheritdoc />
public override void Write(string value) public override void Write(string value)
{ {
Content.Append(value); Content.AppendEncoded(value);
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Write(char value) public override void Write(char value)
{ {
Content.Append(value.ToString()); Content.AppendEncoded(value.ToString());
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -7,6 +7,7 @@ using System.Globalization;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Mvc.Razor.TagHelpers; using Microsoft.AspNet.Mvc.Razor.TagHelpers;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.TagHelpers.Internal; using Microsoft.AspNet.Mvc.TagHelpers.Internal;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.Caching.Memory; using Microsoft.Framework.Caching.Memory;
@ -265,7 +266,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
// Only HrefInclude is specified. Don't render the original tag. // Only HrefInclude is specified. Don't render the original tag.
output.TagName = null; output.TagName = null;
output.Content.SetContent(string.Empty); output.Content.SetContent(HtmlString.Empty);
} }
} }
@ -323,26 +324,27 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
} }
} }
builder.Append(Environment.NewLine); builder.Append(HtmlString.NewLine);
// Build the <meta /> tag that's used to test for the presence of the stylesheet // Build the <meta /> tag that's used to test for the presence of the stylesheet
builder.AppendFormat( builder
CultureInfo.InvariantCulture, .AppendEncoded("<meta name=\"x-stylesheet-fallback-test\" class=\"")
"<meta name=\"x-stylesheet-fallback-test\" class=\"{0}\" />", .Append(FallbackTestClass)
HtmlEncoder.HtmlEncode(FallbackTestClass)); .AppendEncoded("\" />");
// Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra // Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
// <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false, // <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,
// indicating that the primary stylesheet failed to load. // indicating that the primary stylesheet failed to load.
builder builder
.Append("<script>") .AppendEncoded("<script>")
.AppendFormat( .AppendEncoded(
CultureInfo.InvariantCulture, string.Format(
JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName), CultureInfo.InvariantCulture,
JavaScriptEncoder.JavaScriptStringEncode(FallbackTestProperty), JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName),
JavaScriptEncoder.JavaScriptStringEncode(FallbackTestValue), JavaScriptEncoder.JavaScriptStringEncode(FallbackTestProperty),
JavaScriptStringArrayEncoder.Encode(JavaScriptEncoder, fallbackHrefs)) JavaScriptEncoder.JavaScriptStringEncode(FallbackTestValue),
.Append("</script>"); JavaScriptStringArrayEncoder.Encode(JavaScriptEncoder, fallbackHrefs)))
.AppendEncoded("</script>");
} }
} }
@ -370,7 +372,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
private void BuildLinkTag(TagHelperAttributeList attributes, TagHelperContent builder) private void BuildLinkTag(TagHelperAttributeList attributes, TagHelperContent builder)
{ {
builder.Append("<link "); builder.AppendEncoded("<link ");
foreach (var attribute in attributes) foreach (var attribute in attributes)
{ {
@ -389,13 +391,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
} }
builder builder
.Append(attribute.Name) .AppendEncoded(attribute.Name)
.Append("=\"") .AppendEncoded("=\"")
.Append(HtmlEncoder, ViewContext.Writer.Encoding, attributeValue) .Append(HtmlEncoder, ViewContext.Writer.Encoding, attributeValue)
.Append("\" "); .AppendEncoded("\" ");
} }
builder.Append("/>"); builder.AppendEncoded("/>");
} }
private enum Mode private enum Mode

View File

@ -282,10 +282,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
if (fallbackSrcs.Any()) if (fallbackSrcs.Any())
{ {
// Build the <script> tag that checks the test method and if it fails, renders the extra script. // Build the <script> tag that checks the test method and if it fails, renders the extra script.
builder.Append(Environment.NewLine) builder.AppendEncoded(Environment.NewLine)
.Append("<script>(") .AppendEncoded("<script>(")
.Append(FallbackTestExpression) .AppendEncoded(FallbackTestExpression)
.Append("||document.write(\""); .AppendEncoded("||document.write(\"");
// May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound. // May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound.
if (!attributes.ContainsName(SrcAttributeName)) if (!attributes.ContainsName(SrcAttributeName))
@ -299,7 +299,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Fallback "src" values come from bound attributes and globbing. Must always be non-null. // Fallback "src" values come from bound attributes and globbing. Must always be non-null.
Debug.Assert(src != null); Debug.Assert(src != null);
builder.Append("<script"); builder.AppendEncoded("<script");
foreach (var attribute in attributes) foreach (var attribute in attributes)
{ {
@ -327,10 +327,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
} }
} }
builder.Append("><\\/script>"); builder.AppendEncoded("><\\/script>");
} }
builder.Append("\"));</script>"); builder.AppendEncoded("\"));</script>");
} }
} }
@ -360,7 +360,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
TagHelperAttributeList attributes, TagHelperAttributeList attributes,
TagHelperContent builder) TagHelperContent builder)
{ {
builder.Append("<script"); builder.AppendEncoded("<script");
foreach (var attribute in attributes) foreach (var attribute in attributes)
{ {
@ -381,29 +381,29 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
AppendAttribute(builder, attribute.Name, attributeValue, escapeQuotes: false); AppendAttribute(builder, attribute.Name, attributeValue, escapeQuotes: false);
} }
builder.Append("></script>"); builder.AppendEncoded("></script>");
} }
private void AppendAttribute(TagHelperContent content, string key, object value, bool escapeQuotes) private void AppendAttribute(TagHelperContent content, string key, object value, bool escapeQuotes)
{ {
content content
.Append(" ") .AppendEncoded(" ")
.Append(key); .AppendEncoded(key);
if (escapeQuotes) if (escapeQuotes)
{ {
// Passed only JavaScript-encoded strings in this case. Do not perform HTML-encoding as well. // Passed only JavaScript-encoded strings in this case. Do not perform HTML-encoding as well.
content content
.Append("=\\\"") .AppendEncoded("=\\\"")
.Append((string)value) .AppendEncoded((string)value)
.Append("\\\""); .AppendEncoded("\\\"");
} }
else else
{ {
// HTML-encoded the given value if necessary. // HTML-encoded the given value if necessary.
content content
.Append("=\"") .AppendEncoded("=\"")
.Append(HtmlEncoder, ViewContext.Writer.Encoding, value) .Append(HtmlEncoder, ViewContext.Writer.Encoding, value)
.Append("\""); .AppendEncoded("\"");
} }
} }

View File

@ -283,7 +283,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var innerContent = new BufferedHtmlContent(); var innerContent = new BufferedHtmlContent();
innerContent.Append(templateBuilderResult); innerContent.Append(templateBuilderResult);
innerContent.Append(" "); innerContent.AppendEncoded(" ");
innerContent.Append(htmlHelper.ValidationMessage( innerContent.Append(htmlHelper.ValidationMessage(
propertyMetadata.PropertyName, propertyMetadata.PropertyName,
message: null, message: null,

View File

@ -539,8 +539,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
// The first newline is always trimmed when a TextArea is rendered, so we add an extra one // The first newline is always trimmed when a TextArea is rendered, so we add an extra one
// in case the value being rendered is something like "\r\nHello". // in case the value being rendered is something like "\r\nHello".
var innerContent = new BufferedHtmlContent(); var innerContent = new BufferedHtmlContent();
innerContent.Append(Environment.NewLine); innerContent.Append(HtmlString.NewLine);
innerContent.Append(new StringHtmlContent(value)); innerContent.Append(value);
tagBuilder.InnerHtml = innerContent; tagBuilder.InnerHtml = innerContent;
return tagBuilder; return tagBuilder;
@ -704,7 +704,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
if (!isHtmlSummaryModified) if (!isHtmlSummaryModified)
{ {
htmlSummary.AppendLine(HiddenListItem); htmlSummary.AppendEncoded(HiddenListItem);
htmlSummary.Append(HtmlString.NewLine);
} }
var unorderedList = new TagBuilder("ul") var unorderedList = new TagBuilder("ul")
@ -1316,7 +1317,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
groupBuilder.MergeAttribute("disabled", "disabled"); groupBuilder.MergeAttribute("disabled", "disabled");
} }
var optGroupContent = new BufferedHtmlContent().Append(Environment.NewLine); var optGroupContent = new BufferedHtmlContent().Append(HtmlString.NewLine);
foreach (var item in group) foreach (var item in group)
{ {
optGroupContent.AppendLine(GenerateOption(item)); optGroupContent.AppendLine(GenerateOption(item));

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO; using System.IO;
using Microsoft.AspNet.Html.Abstractions; using Microsoft.AspNet.Html.Abstractions;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
@ -20,6 +21,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// </summary> /// </summary>
public static readonly HtmlString Empty = new HtmlString(string.Empty); public static readonly HtmlString Empty = new HtmlString(string.Empty);
/// <summary>
/// Returns an <see cref="HtmlString"/> containing <see cref="Environment.NewLine"/>.
/// </summary>
public static readonly HtmlString NewLine = new HtmlString(Environment.NewLine);
/// <summary> /// <summary>
/// Creates a new instance of <see cref="HtmlString"/>. /// Creates a new instance of <see cref="HtmlString"/>.
/// </summary> /// </summary>

View File

@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders; using Microsoft.Framework.WebEncoders;
@ -19,8 +21,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// </remarks> /// </remarks>
public class StringCollectionTextWriter : TextWriter public class StringCollectionTextWriter : TextWriter
{ {
private const int MaxCharToStringLength = 1024;
private static readonly Task _completedTask = Task.FromResult(0); private static readonly Task _completedTask = Task.FromResult(0);
private readonly Encoding _encoding; private readonly Encoding _encoding;
private readonly StringCollectionTextWriterContent _content;
/// <summary> /// <summary>
/// Creates a new instance of <see cref="StringCollectionTextWriter"/>. /// Creates a new instance of <see cref="StringCollectionTextWriter"/>.
@ -29,7 +34,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
public StringCollectionTextWriter(Encoding encoding) public StringCollectionTextWriter(Encoding encoding)
{ {
_encoding = encoding; _encoding = encoding;
Content = new BufferedHtmlContent(); Entries = new List<object>();
_content = new StringCollectionTextWriterContent(Entries);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -39,15 +45,17 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
/// <summary> /// <summary>
/// A collection of entries buffered by this instance of <see cref="StringCollectionTextWriter"/>. /// Gets the content written to the writer as an <see cref="IHtmlContent"/>.
/// </summary> /// </summary>
public IHtmlContent Content => _content;
// internal for testing purposes. // internal for testing purposes.
internal BufferedHtmlContent Content { get; } internal List<object> Entries { get; }
/// <inheritdoc /> /// <inheritdoc />
public override void Write(char value) public override void Write(char value)
{ {
Content.Append(value.ToString()); _content.Append(value.ToString());
} }
/// <inheritdoc /> /// <inheritdoc />
@ -62,7 +70,19 @@ namespace Microsoft.AspNet.Mvc.Rendering
throw new ArgumentOutOfRangeException(nameof(count)); throw new ArgumentOutOfRangeException(nameof(count));
} }
Content.Append(buffer, index, count); while (count > 0)
{
// Split large char arrays into 1KB strings.
var currentCount = count;
if (MaxCharToStringLength < currentCount)
{
currentCount = MaxCharToStringLength;
}
_content.Append(new string(buffer, index, currentCount));
index += currentCount;
count -= currentCount;
}
} }
/// <inheritdoc /> /// <inheritdoc />
@ -73,7 +93,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return; return;
} }
Content.Append(value); _content.Append(value);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -100,7 +120,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <inheritdoc /> /// <inheritdoc />
public override void WriteLine() public override void WriteLine()
{ {
Content.Append(Environment.NewLine); _content.Append(Environment.NewLine);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -149,7 +169,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var targetStringCollectionWriter = writer as StringCollectionTextWriter; var targetStringCollectionWriter = writer as StringCollectionTextWriter;
if (targetStringCollectionWriter != null) if (targetStringCollectionWriter != null)
{ {
targetStringCollectionWriter.Content.Append(Content); targetStringCollectionWriter._content.Append(Content);
} }
else else
{ {
@ -178,5 +198,46 @@ namespace Microsoft.AspNet.Mvc.Rendering
return writer.ToString(); return writer.ToString();
} }
} }
internal class StringCollectionTextWriterContent : IHtmlContent
{
private readonly List<object> _entries;
public StringCollectionTextWriterContent(List<object> entries)
{
_entries = entries;
}
public void Append(string value)
{
_entries.Add(value);
}
public void Append(IHtmlContent content)
{
_entries.Add(content);
}
public void WriteTo(TextWriter writer, IHtmlEncoder encoder)
{
foreach (var item in _entries)
{
if (item == null)
{
continue;
}
var itemAsString = item as string;
if (itemAsString != null)
{
writer.Write(itemAsString);
}
else
{
((IHtmlContent)item).WriteTo(writer, encoder);
}
}
}
}
} }
} }

View File

@ -173,7 +173,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var page = CreatePage(v => var page = CreatePage(v =>
{ {
v.HtmlEncoder = new CommonTestEncoder(); v.HtmlEncoder = new CommonTestEncoder();
v.StartTagHelperWritingScope(new RazorTextWriter(TextWriter.Null, Encoding.UTF8)); v.StartTagHelperWritingScope(new RazorTextWriter(TextWriter.Null, Encoding.UTF8, v.HtmlEncoder));
v.Write("Hello "); v.Write("Hello ");
v.Write("World!"); v.Write("World!");
var returnValue = v.EndTagHelperWritingScope(); var returnValue = v.EndTagHelperWritingScope();
@ -1018,15 +1018,11 @@ namespace Microsoft.AspNet.Mvc.Razor
public async Task Write_WithHtmlString_WritesValueWithoutEncoding() public async Task Write_WithHtmlString_WritesValueWithoutEncoding()
{ {
// Arrange // Arrange
var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var stringCollectionWriter = new StringCollectionTextWriter(Encoding.UTF8);
stringCollectionWriter.Write("text1");
stringCollectionWriter.Write("text2");
var page = CreatePage(p => var page = CreatePage(p =>
{ {
p.Write(new HtmlString("Hello world")); p.Write(new HtmlString("Hello world"));
p.Write(stringCollectionWriter.Content);
}); });
page.ViewContext.Writer = writer; page.ViewContext.Writer = writer;
@ -1034,11 +1030,9 @@ namespace Microsoft.AspNet.Mvc.Razor
await page.ExecuteAsync(); await page.ExecuteAsync();
// Assert // Assert
var buffer = writer.BufferedWriter.Content.Entries; var buffer = writer.BufferedWriter.Entries;
Assert.Equal(3, buffer.Count); Assert.Equal(1, buffer.Count);
Assert.Equal("Hello world", buffer[0]); Assert.Equal("Hello world", buffer[0]);
Assert.Equal("text1", buffer[1]);
Assert.Equal("text2", buffer[2]);
} }
public static TheoryData<TagHelperOutput, string> WriteTagHelper_InputData public static TheoryData<TagHelperOutput, string> WriteTagHelper_InputData
@ -1688,7 +1682,7 @@ namespace Microsoft.AspNet.Mvc.Razor
uniqueId: string.Empty, uniqueId: string.Empty,
executeChildContentAsync: () => executeChildContentAsync: () =>
{ {
defaultTagHelperContent.SetContent(input); defaultTagHelperContent.AppendEncoded(input);
return Task.FromResult(result: true); return Task.FromResult(result: true);
}, },
startTagHelperWritingScope: () => { }, startTagHelperWritingScope: () => { },
@ -1726,11 +1720,12 @@ namespace Microsoft.AspNet.Mvc.Razor
startTagHelperWritingScope: () => { }, startTagHelperWritingScope: () => { },
endTagHelperWritingScope: () => new DefaultTagHelperContent()); endTagHelperWritingScope: () => new DefaultTagHelperContent());
tagHelperExecutionContext.Output = new TagHelperOutput("p", new TagHelperAttributeList()); tagHelperExecutionContext.Output = new TagHelperOutput("p", new TagHelperAttributeList());
tagHelperExecutionContext.Output.Content.SetContent("Hello World!"); tagHelperExecutionContext.Output.Content.AppendEncoded("Hello World!");
// Act // Act
var page = CreatePage(p => var page = CreatePage(p =>
{ {
p.HtmlEncoder = new CommonTestEncoder();
p.WriteTagHelperToAsync(writer, tagHelperExecutionContext).Wait(); p.WriteTagHelperToAsync(writer, tagHelperExecutionContext).Wait();
}, context); }, context);
await page.ExecuteAsync(); await page.ExecuteAsync();
@ -1783,11 +1778,11 @@ namespace Microsoft.AspNet.Mvc.Razor
TagMode = tagMode TagMode = tagMode
}; };
output.PreElement.SetContent(preElement); output.PreElement.AppendEncoded(preElement);
output.PreContent.SetContent(preContent); output.PreContent.AppendEncoded(preContent);
output.Content.SetContent(content); output.Content.AppendEncoded(content);
output.PostContent.SetContent(postContent); output.PostContent.AppendEncoded(postContent);
output.PostElement.SetContent(postElement); output.PostElement.AppendEncoded(postElement);
return output; return output;
} }

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing;
using Microsoft.Framework.WebEncoders.Testing;
using Moq; using Moq;
using Xunit; using Xunit;
@ -20,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
{ {
// Arrange // Arrange
var expected = new[] { "True", "3", "18446744073709551615", "Hello world", "3.14", "2.718", "m" }; var expected = new[] { "True", "3", "18446744073709551615", "Hello world", "3.14", "2.718", "m" };
var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
writer.Write(true); writer.Write(true);
@ -32,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
writer.Write('m'); writer.Write('m');
// Assert // Assert
Assert.Equal(expected, writer.BufferedWriter.Content.Entries); Assert.Equal(expected, writer.BufferedWriter.Entries);
} }
[Fact] [Fact]
@ -42,7 +43,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
// Arrange // Arrange
var expected = new[] { "True", "3", "18446744073709551615", "Hello world", "3.14", "2.718" }; var expected = new[] { "True", "3", "18446744073709551615", "Hello world", "3.14", "2.718" };
var unbufferedWriter = new Mock<TextWriter>(); var unbufferedWriter = new Mock<TextWriter>();
var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8); var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new CommonTestEncoder());
var testClass = new TestClass(); var testClass = new TestClass();
// Act // Act
@ -55,7 +56,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
writer.Write(2.718m); writer.Write(2.718m);
// Assert // Assert
Assert.Empty(writer.BufferedWriter.Content.Entries); Assert.Empty(writer.BufferedWriter.Entries);
foreach (var item in expected) foreach (var item in expected)
{ {
unbufferedWriter.Verify(v => v.Write(item), Times.Once()); unbufferedWriter.Verify(v => v.Write(item), Times.Once());
@ -68,7 +69,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
{ {
// Arrange // Arrange
var unbufferedWriter = new Mock<TextWriter> { CallBase = true }; var unbufferedWriter = new Mock<TextWriter> { CallBase = true };
var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8); var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new CommonTestEncoder());
var buffer1 = new[] { 'a', 'b', 'c', 'd' }; var buffer1 = new[] { 'a', 'b', 'c', 'd' };
var buffer2 = new[] { 'd', 'e', 'f' }; var buffer2 = new[] { 'd', 'e', 'f' };
@ -81,7 +82,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
await writer.WriteLineAsync(buffer1); await writer.WriteLineAsync(buffer1);
// Assert // Assert
Assert.Empty(writer.BufferedWriter.Content.Entries); Assert.Empty(writer.BufferedWriter.Entries);
unbufferedWriter.Verify(v => v.Write('x'), Times.Once()); unbufferedWriter.Verify(v => v.Write('x'), Times.Once());
unbufferedWriter.Verify(v => v.Write(buffer1, 1, 2), Times.Once()); unbufferedWriter.Verify(v => v.Write(buffer1, 1, 2), Times.Once());
unbufferedWriter.Verify(v => v.Write(buffer1, 0, 4), Times.Once()); unbufferedWriter.Verify(v => v.Write(buffer1, 0, 4), Times.Once());
@ -96,7 +97,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
{ {
// Arrange // Arrange
var unbufferedWriter = new Mock<TextWriter>(); var unbufferedWriter = new Mock<TextWriter>();
var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8); var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
await writer.FlushAsync(); await writer.FlushAsync();
@ -106,7 +107,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
await writer.WriteLineAsync("gh"); await writer.WriteLineAsync("gh");
// Assert // Assert
Assert.Empty(writer.BufferedWriter.Content.Entries); Assert.Empty(writer.BufferedWriter.Entries);
unbufferedWriter.Verify(v => v.Write("a"), Times.Once()); unbufferedWriter.Verify(v => v.Write("a"), Times.Once());
unbufferedWriter.Verify(v => v.WriteLine("ab"), Times.Once()); unbufferedWriter.Verify(v => v.WriteLine("ab"), Times.Once());
unbufferedWriter.Verify(v => v.WriteAsync("ef"), Times.Once()); unbufferedWriter.Verify(v => v.WriteAsync("ef"), Times.Once());
@ -120,7 +121,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
// Arrange // Arrange
var newLine = Environment.NewLine; var newLine = Environment.NewLine;
var expected = new List<object> { "False", newLine, "1.1", newLine, "3", newLine }; var expected = new List<object> { "False", newLine, "1.1", newLine, "3", newLine };
var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
writer.WriteLine(false); writer.WriteLine(false);
@ -128,7 +129,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
writer.WriteLine(3L); writer.WriteLine(3L);
// Assert // Assert
Assert.Equal(expected, writer.BufferedWriter.Content.Entries); Assert.Equal(expected, writer.BufferedWriter.Entries);
} }
[Fact] [Fact]
@ -137,7 +138,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
{ {
// Arrange // Arrange
var unbufferedWriter = new Mock<TextWriter>(); var unbufferedWriter = new Mock<TextWriter>();
var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8); var writer = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
writer.Flush(); writer.Flush();
@ -146,7 +147,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
writer.WriteLine(3L); writer.WriteLine(3L);
// Assert // Assert
Assert.Empty(writer.BufferedWriter.Content.ToString()); Assert.Empty(writer.BufferedWriter.Entries);
unbufferedWriter.Verify(v => v.Write("False"), Times.Once()); unbufferedWriter.Verify(v => v.Write("False"), Times.Once());
unbufferedWriter.Verify(v => v.Write("1.1"), Times.Once()); unbufferedWriter.Verify(v => v.Write("1.1"), Times.Once());
unbufferedWriter.Verify(v => v.Write("3"), Times.Once()); unbufferedWriter.Verify(v => v.Write("3"), Times.Once());
@ -160,7 +161,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
var input1 = new ArraySegment<char>(new char[] { 'a', 'b', 'c', 'd' }, 1, 3); var input1 = new ArraySegment<char>(new char[] { 'a', 'b', 'c', 'd' }, 1, 3);
var input2 = new ArraySegment<char>(new char[] { 'e', 'f' }, 0, 2); var input2 = new ArraySegment<char>(new char[] { 'e', 'f' }, 0, 2);
var input3 = new ArraySegment<char>(new char[] { 'g', 'h', 'i', 'j' }, 3, 1); var input3 = new ArraySegment<char>(new char[] { 'g', 'h', 'i', 'j' }, 3, 1);
var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
writer.Write(input1.Array, input1.Offset, input1.Count); writer.Write(input1.Array, input1.Offset, input1.Count);
@ -168,7 +169,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
await writer.WriteLineAsync(input3.Array, input3.Offset, input3.Count); await writer.WriteLineAsync(input3.Array, input3.Offset, input3.Count);
// Assert // Assert
var buffer = writer.BufferedWriter.Content.Entries; var buffer = writer.BufferedWriter.Entries;
Assert.Equal(4, buffer.Count); Assert.Equal(4, buffer.Count);
Assert.Equal("bcd", buffer[0]); Assert.Equal("bcd", buffer[0]);
Assert.Equal("ef", buffer[1]); Assert.Equal("ef", buffer[1]);
@ -181,14 +182,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
{ {
// Arrange // Arrange
var newLine = Environment.NewLine; var newLine = Environment.NewLine;
var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
writer.WriteLine(); writer.WriteLine();
await writer.WriteLineAsync(); await writer.WriteLineAsync();
// Assert // Assert
var actual = writer.BufferedWriter.Content.Entries; var actual = writer.BufferedWriter.Entries;
Assert.Equal<object>(new[] { newLine, newLine }, actual); Assert.Equal<object>(new[] { newLine, newLine }, actual);
} }
@ -201,7 +202,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
var input2 = "from"; var input2 = "from";
var input3 = "ASP"; var input3 = "ASP";
var input4 = ".Net"; var input4 = ".Net";
var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
writer.Write(input1); writer.Write(input1);
@ -210,7 +211,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
await writer.WriteLineAsync(input4); await writer.WriteLineAsync(input4);
// Assert // Assert
var actual = writer.BufferedWriter.Content.Entries; var actual = writer.BufferedWriter.Entries;
Assert.Equal<object>(new[] { input1, input2, newLine, input3, input4, newLine }, actual); Assert.Equal<object>(new[] { input1, input2, newLine, input3, input4, newLine }, actual);
} }
@ -218,8 +219,8 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
public void Copy_CopiesContent_IfTargetTextWriterIsARazorTextWriterAndBuffering() public void Copy_CopiesContent_IfTargetTextWriterIsARazorTextWriterAndBuffering()
{ {
// Arrange // Arrange
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var target = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
source.Write("Hello world"); source.Write("Hello world");
@ -228,9 +229,9 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
// Assert // Assert
// Make sure content was written to the source. // Make sure content was written to the source.
Assert.Equal(2, source.BufferedWriter.Content.Entries.Count); Assert.Equal(2, source.BufferedWriter.Entries.Count);
Assert.Equal(1, target.BufferedWriter.Content.Entries.Count); Assert.Equal(1, target.BufferedWriter.Entries.Count);
Assert.Same(source.BufferedWriter.Content, Assert.Single(target.BufferedWriter.Content.Entries)); Assert.Same(source.BufferedWriter.Content, Assert.Single(target.BufferedWriter.Entries));
} }
[Fact] [Fact]
@ -238,8 +239,8 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
{ {
// Arrange // Arrange
var unbufferedWriter = new Mock<TextWriter>(); var unbufferedWriter = new Mock<TextWriter>();
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8); var target = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
target.Flush(); target.Flush();
@ -249,8 +250,8 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
// Assert // Assert
// Make sure content was written to the source. // Make sure content was written to the source.
Assert.Equal(2, source.BufferedWriter.Content.Entries.Count); Assert.Equal(2, source.BufferedWriter.Entries.Count);
Assert.Empty(target.BufferedWriter.Content.ToString()); Assert.Empty(target.BufferedWriter.Entries);
unbufferedWriter.Verify(v => v.Write("Hello world"), Times.Once()); unbufferedWriter.Verify(v => v.Write("Hello world"), Times.Once());
unbufferedWriter.Verify(v => v.Write("bc"), Times.Once()); unbufferedWriter.Verify(v => v.Write("bc"), Times.Once());
} }
@ -259,7 +260,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
public void Copy_WritesContent_IfTargetTextWriterIsNotARazorTextWriter() public void Copy_WritesContent_IfTargetTextWriterIsNotARazorTextWriter()
{ {
// Arrange // Arrange
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new StringWriter(); var target = new StringWriter();
var expected = @"Hello world var expected = @"Hello world
abc"; abc";
@ -277,8 +278,8 @@ abc";
public async Task CopyAsync_WritesContent_IfTargetTextWriterIsARazorTextWriterAndBuffering() public async Task CopyAsync_WritesContent_IfTargetTextWriterIsARazorTextWriterAndBuffering()
{ {
// Arrange // Arrange
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var target = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
source.WriteLine("Hello world"); source.WriteLine("Hello world");
@ -286,9 +287,9 @@ abc";
await source.CopyToAsync(target); await source.CopyToAsync(target);
// Assert // Assert
Assert.Equal(3, source.BufferedWriter.Content.Entries.Count); Assert.Equal(3, source.BufferedWriter.Entries.Count);
Assert.Equal(1, target.BufferedWriter.Content.Entries.Count); Assert.Equal(1, target.BufferedWriter.Entries.Count);
Assert.Equal(source.BufferedWriter.Content, Assert.Single(target.BufferedWriter.Content.Entries)); Assert.Equal(source.BufferedWriter.Content, Assert.Single(target.BufferedWriter.Entries));
} }
//[Fact] //[Fact]
@ -297,8 +298,8 @@ abc";
{ {
// Arrange // Arrange
var unbufferedWriter = new Mock<TextWriter>(); var unbufferedWriter = new Mock<TextWriter>();
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8); var target = new RazorTextWriter(unbufferedWriter.Object, Encoding.UTF8, new CommonTestEncoder());
// Act // Act
await target.FlushAsync(); await target.FlushAsync();
@ -308,7 +309,7 @@ abc";
// Assert // Assert
// Make sure content was written to the source. // Make sure content was written to the source.
Assert.Equal(3, source.BufferedWriter.Content.Entries.Count); Assert.Equal(3, source.BufferedWriter.Entries.Count);
Assert.Empty(target.BufferedWriter.Content.ToString()); Assert.Empty(target.BufferedWriter.Content.ToString());
unbufferedWriter.Verify(v => v.WriteAsync("Hello from Asp.Net"), Times.Once()); 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(Environment.NewLine), Times.Once());
@ -319,7 +320,7 @@ abc";
public async Task CopyAsync_WritesContent_IfTargetTextWriterIsNotARazorTextWriter() public async Task CopyAsync_WritesContent_IfTargetTextWriterIsNotARazorTextWriter()
{ {
// Arrange // Arrange
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new StringWriter(); var target = new StringWriter();
var expected = @"Hello world var expected = @"Hello world
"; ";

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Framework.WebEncoders.Testing;
using Moq; using Moq;
using Xunit; using Xunit;
@ -16,7 +17,8 @@ namespace Microsoft.AspNet.Mvc.Razor
// Arrange // Arrange
var factory = new RazorViewFactory( var factory = new RazorViewFactory(
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
Mock.Of<IViewStartProvider>()); Mock.Of<IViewStartProvider>(),
new CommonTestEncoder());
var page = Mock.Of<IRazorPage>(); var page = Mock.Of<IRazorPage>();
var viewEngine = Mock.Of<IRazorViewEngine>(); var viewEngine = Mock.Of<IRazorViewEngine>();
@ -35,7 +37,8 @@ namespace Microsoft.AspNet.Mvc.Razor
// Arrange // Arrange
var factory = new RazorViewFactory( var factory = new RazorViewFactory(
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
Mock.Of<IViewStartProvider>()); Mock.Of<IViewStartProvider>(),
new CommonTestEncoder());
var page = Mock.Of<IRazorPage>(); var page = Mock.Of<IRazorPage>();
var viewEngine = Mock.Of<IRazorViewEngine>(); var viewEngine = Mock.Of<IRazorViewEngine>();

View File

@ -40,6 +40,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: true); isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
var expected = viewContext.Writer; var expected = viewContext.Writer;
@ -68,6 +69,7 @@ namespace Microsoft.AspNet.Mvc.Razor
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: true); isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -131,6 +133,7 @@ namespace Microsoft.AspNet.Mvc.Razor
activator, activator,
CreateViewStartProvider(viewStart), CreateViewStartProvider(viewStart),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -155,6 +158,7 @@ namespace Microsoft.AspNet.Mvc.Razor
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: true); isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -199,6 +203,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
viewStartProvider, viewStartProvider,
page, page,
new CommonTestEncoder(),
isPartial: true); isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -224,6 +229,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
var original = viewContext.Writer; var original = viewContext.Writer;
@ -248,6 +254,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
var original = viewContext.Writer; var original = viewContext.Writer;
@ -274,6 +281,7 @@ namespace Microsoft.AspNet.Mvc.Razor
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -316,6 +324,7 @@ namespace Microsoft.AspNet.Mvc.Razor
activator.Object, activator.Object,
CreateViewStartProvider(viewStart1, viewStart2), CreateViewStartProvider(viewStart1, viewStart2),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -348,6 +357,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
Mock.Of<IViewStartProvider>(), Mock.Of<IViewStartProvider>(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
viewEngine.Setup(v => v.FindPage(viewContext, layoutPath)) viewEngine.Setup(v => v.FindPage(viewContext, layoutPath))
@ -411,6 +421,7 @@ namespace Microsoft.AspNet.Mvc.Razor
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
viewEngine.Setup(p => p.FindPage(viewContext, LayoutPath)) viewEngine.Setup(p => p.FindPage(viewContext, LayoutPath))
@ -452,6 +463,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -514,6 +526,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -571,6 +584,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -630,6 +644,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -694,6 +709,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -725,6 +741,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -784,6 +801,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -847,6 +865,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -899,6 +918,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -948,6 +968,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -977,6 +998,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -1021,6 +1043,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -1096,6 +1119,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
viewStartProvider.Object, viewStartProvider.Object,
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
viewContext.HttpContext.Features.Set<IPageExecutionListenerFeature>(feature.Object); viewContext.HttpContext.Features.Set<IPageExecutionListenerFeature>(feature.Object);
@ -1141,6 +1165,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
Mock.Of<IViewStartProvider>(), Mock.Of<IViewStartProvider>(),
page, page,
new CommonTestEncoder(),
isPartial: true); isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
viewContext.Writer = writer; viewContext.Writer = writer;
@ -1172,6 +1197,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
Mock.Of<IViewStartProvider>(), Mock.Of<IViewStartProvider>(),
page, page,
new CommonTestEncoder(),
isPartial); isPartial);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -1211,6 +1237,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(viewStart1, viewStart2), CreateViewStartProvider(viewStart1, viewStart2),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -1248,6 +1275,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(viewStart1, viewStart2), CreateViewStartProvider(viewStart1, viewStart2),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -1288,6 +1316,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(viewStart), CreateViewStartProvider(viewStart),
page, page,
new CommonTestEncoder(),
isPartial: false); isPartial: false);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
@ -1313,6 +1342,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider(),
page, page,
new CommonTestEncoder(),
isPartial: true); isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);

View File

@ -95,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
TagMode = TagMode.SelfClosing, TagMode = TagMode.SelfClosing,
}; };
output.Content.SetContent(originalContent); output.Content.AppendEncoded(originalContent);
var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider()); var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider());
var tagHelper = GetTagHelper(htmlGenerator, model: false, propertyName: nameof(Model.IsACar)); var tagHelper = GetTagHelper(htmlGenerator, model: false, propertyName: nameof(Model.IsACar));
@ -270,9 +270,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
TagMode = TagMode.SelfClosing, TagMode = TagMode.SelfClosing,
}; };
output.PreContent.SetContent(expectedPreContent); output.PreContent.AppendEncoded(expectedPreContent);
output.Content.SetContent(originalContent); output.Content.AppendEncoded(originalContent);
output.PostContent.SetContent(expectedPostContent); output.PostContent.AppendEncoded(expectedPostContent);
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model: false, propertyName: nameof(Model.IsACar)); var tagHelper = GetTagHelper(htmlGenerator.Object, model: false, propertyName: nameof(Model.IsACar));

View File

@ -196,7 +196,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: useCachedResult => getChildContentAsync: useCachedResult =>
{ {
var tagHelperContent = new DefaultTagHelperContent(); var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(tagHelperOutputContent.OriginalChildContent); tagHelperContent.AppendEncoded(tagHelperOutputContent.OriginalChildContent);
return Task.FromResult<TagHelperContent>(tagHelperContent); return Task.FromResult<TagHelperContent>(tagHelperContent);
}); });
var htmlAttributes = new TagHelperAttributeList var htmlAttributes = new TagHelperAttributeList
@ -204,14 +204,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, htmlAttributes); var output = new TagHelperOutput(expectedTagName, htmlAttributes);
output.PreContent.SetContent(expectedPreContent); output.PreContent.AppendEncoded(expectedPreContent);
output.PostContent.SetContent(expectedPostContent); output.PostContent.AppendEncoded(expectedPostContent);
// LabelTagHelper checks IsContentModified so we don't want to forcibly set it if // LabelTagHelper checks IsContentModified so we don't want to forcibly set it if
// tagHelperOutputContent.OriginalContent is going to be null or empty. // tagHelperOutputContent.OriginalContent is going to be null or empty.
if (!string.IsNullOrEmpty(tagHelperOutputContent.OriginalContent)) if (!string.IsNullOrEmpty(tagHelperOutputContent.OriginalContent))
{ {
output.Content.SetContent(tagHelperOutputContent.OriginalContent); output.Content.AppendEncoded(tagHelperOutputContent.OriginalContent);
} }
var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);

View File

@ -293,16 +293,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: useCachedResult => getChildContentAsync: useCachedResult =>
{ {
var tagHelperContent = new DefaultTagHelperContent(); var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something"); tagHelperContent.AppendEncoded("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent); return Task.FromResult<TagHelperContent>(tagHelperContent);
}); });
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes)
{ {
TagMode = TagMode.SelfClosing, TagMode = TagMode.SelfClosing,
}; };
output.PreContent.SetContent(expectedPreContent); output.PreContent.AppendEncoded(expectedPreContent);
output.Content.SetContent(expectedContent); output.Content.AppendEncoded(expectedContent);
output.PostContent.SetContent(originalPostContent); output.PostContent.AppendEncoded(originalPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider) var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
{ {
@ -395,16 +395,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: useCachedResult => getChildContentAsync: useCachedResult =>
{ {
var tagHelperContent = new DefaultTagHelperContent(); var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something"); tagHelperContent.AppendEncoded("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent); return Task.FromResult<TagHelperContent>(tagHelperContent);
}); });
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes)
{ {
TagMode = TagMode.SelfClosing, TagMode = TagMode.SelfClosing,
}; };
output.PreContent.SetContent(expectedPreContent); output.PreContent.AppendEncoded(expectedPreContent);
output.Content.SetContent(expectedContent); output.Content.AppendEncoded(expectedContent);
output.PostContent.SetContent(originalPostContent); output.PostContent.AppendEncoded(originalPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider) var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
{ {

View File

@ -167,7 +167,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var output = new TagHelperOutput( var output = new TagHelperOutput(
"span", "span",
attributes: new TagHelperAttributeList()); attributes: new TagHelperAttributeList());
output.Content.SetContent(outputContent); output.Content.AppendEncoded(outputContent);
var context = new TagHelperContext( var context = new TagHelperContext(
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>( allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
@ -177,7 +177,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: useCachedResult => getChildContentAsync: useCachedResult =>
{ {
var tagHelperContent = new DefaultTagHelperContent(); var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(childContent); tagHelperContent.AppendEncoded(childContent);
return Task.FromResult<TagHelperContent>(tagHelperContent); return Task.FromResult<TagHelperContent>(tagHelperContent);
}); });

View File

@ -5,6 +5,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Html.Abstractions; using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.TestCommon;
using Moq; using Moq;
using Xunit; using Xunit;
@ -151,7 +152,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var actual = helper.Partial("some-partial"); var actual = helper.Partial("some-partial");
// Assert // Assert
Assert.Equal(expected, actual.ToString()); Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(actual));
} }
[Fact] [Fact]
@ -166,7 +167,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var actual = helper.Partial("some-partial", model); var actual = helper.Partial("some-partial", model);
// Assert // Assert
Assert.Equal(expected, actual.ToString()); Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(actual));
} }
[Fact] [Fact]
@ -182,7 +183,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var actual = helper.Partial("some-partial", viewData); var actual = helper.Partial("some-partial", viewData);
// Assert // Assert
Assert.Equal(expected, actual.ToString()); Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(actual));
} }
private sealed class TestModel private sealed class TestModel

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
writer.Write('m'); writer.Write('m');
// Assert // Assert
Assert.Equal(expected, writer.Content.Entries); Assert.Equal(expected, writer.Entries);
} }
[Fact] [Fact]
@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
writer.WriteLine(3L); writer.WriteLine(3L);
// Assert // Assert
Assert.Equal(expected, writer.Content.Entries); Assert.Equal(expected, writer.Entries);
} }
[Fact] [Fact]
@ -69,7 +69,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
await writer.WriteLineAsync(input3.Array, input3.Offset, input3.Count); await writer.WriteLineAsync(input3.Array, input3.Offset, input3.Count);
// Assert // Assert
var buffer = writer.Content.Entries; var buffer = writer.Entries;
Assert.Equal(4, buffer.Count); Assert.Equal(4, buffer.Count);
Assert.Equal("bcd", buffer[0]); Assert.Equal("bcd", buffer[0]);
Assert.Equal("ef", buffer[1]); Assert.Equal("ef", buffer[1]);
@ -89,7 +89,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
await writer.WriteLineAsync(); await writer.WriteLineAsync();
// Assert // Assert
var actual = writer.Content.Entries; var actual = writer.Entries;
Assert.Equal<object>(new[] { newLine, newLine }, actual); Assert.Equal<object>(new[] { newLine, newLine }, actual);
} }
@ -111,7 +111,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
await writer.WriteLineAsync(input4); await writer.WriteLineAsync(input4);
// Assert // Assert
var actual = writer.Content.Entries; var actual = writer.Entries;
Assert.Equal(new[] { input1, input2, newLine, input3, input4, newLine }, actual); Assert.Equal(new[] { input1, input2, newLine, input3, input4, newLine }, actual);
} }
@ -129,11 +129,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
// Assert // Assert
// Make sure content was written to the source. // Make sure content was written to the source.
Assert.Equal(2, source.Content.Entries.Count); Assert.Equal(2, source.Entries.Count);
Assert.Equal(1, target.Content.Entries.Count); Assert.Equal(1, target.Entries.Count);
var result = Assert.Single(target.Content.Entries);
var bufferedHtmlContent = Assert.IsType<BufferedHtmlContent>(result); var entry = Assert.Single(target.Entries);
Assert.Same(source.Content.Entries, bufferedHtmlContent.Entries); Assert.Same(source.Content, entry);
} }
[Fact] [Fact]

View File

@ -10,20 +10,16 @@ namespace ActivatorWebSite.TagHelpers
[TargetElement("body")] [TargetElement("body")]
public class FooterTagHelper : TagHelper public class FooterTagHelper : TagHelper
{ {
public FooterTagHelper(IHtmlEncoder encoder)
{
Encoder = encoder;
}
public IHtmlEncoder Encoder { get; }
[HtmlAttributeNotBound] [HtmlAttributeNotBound]
[ViewContext] [ViewContext]
public ViewContext ViewContext { get; set; } public ViewContext ViewContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
output.PostContent.SetContent($"<footer>{Encoder.HtmlEncode((string)ViewContext.ViewData["footer"])}</footer>"); output.PostContent
.AppendEncoded("<footer>")
.Append((string)ViewContext.ViewData["footer"])
.AppendEncoded("</footer>");
} }
} }
} }

View File

@ -15,7 +15,7 @@ namespace TagHelpersWebSite.TagHelpers
var childContent = await context.GetChildContentAsync(); var childContent = await context.GetChildContentAsync();
// Find Urls in the content and replace them with their anchor tag equivalent. // Find Urls in the content and replace them with their anchor tag equivalent.
output.Content.SetContent(Regex.Replace( output.Content.AppendEncoded(Regex.Replace(
childContent.GetContent(), childContent.GetContent(),
@"\b(?:https?://|www\.)(\S+)\b", @"\b(?:https?://|www\.)(\S+)\b",
"<strong><a target=\"_blank\" href=\"http://$0\">$0</a></strong>")); "<strong><a target=\"_blank\" href=\"http://$0\">$0</a></strong>"));

View File

@ -19,8 +19,8 @@ namespace TagHelpersWebSite.TagHelpers
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
output.Attributes.RemoveAll("bold"); output.Attributes.RemoveAll("bold");
output.PreContent.SetContent("<b>"); output.PreContent.AppendEncoded("<b>");
output.PostContent.SetContent("</b>"); output.PostContent.AppendEncoded("</b>");
} }
} }
} }

View File

@ -11,7 +11,7 @@ namespace TagHelpersWebSite.TagHelpers
{ {
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
output.Content.SetContent("nested-content"); output.Content.AppendEncoded("nested-content");
} }
} }
} }

View File

@ -11,7 +11,7 @@ namespace TagHelpersWebSite.TagHelpers
{ {
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
output.Content.SetContent("root-content"); output.Content.AppendEncoded("root-content");
} }
} }
} }

View File

@ -23,8 +23,8 @@ namespace TagHelpersWebSite.TagHelpers
{ {
var surroundingTagName = Surround.ToLowerInvariant(); var surroundingTagName = Surround.ToLowerInvariant();
output.PreElement.SetContent($"<{surroundingTagName}>"); output.PreElement.AppendEncoded($"<{surroundingTagName}>");
output.PostElement.SetContent($"</{surroundingTagName}>"); output.PostElement.AppendEncoded($"</{surroundingTagName}>");
} }
} }
} }

View File

@ -50,7 +50,7 @@ namespace MvcSample.Web.Components
writer)); writer));
output.TagName = null; output.TagName = null;
output.Content.SetContent(writer.ToString()); output.Content.AppendEncoded(writer.ToString());
} }
public async Task<IViewComponentResult> InvokeAsync(int count) public async Task<IViewComponentResult> InvokeAsync(int count)

View File

@ -14,7 +14,7 @@ namespace TagHelpersWebSite.TagHelpers
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
output.TagName = "section"; output.TagName = "section";
output.PostContent.SetContent(string.Format( output.PostContent.AppendEncoded(string.Format(
"<p><strong>Version:</strong> {0}</p>" + Environment.NewLine + "<p><strong>Version:</strong> {0}</p>" + Environment.NewLine +
"<p><strong>Copyright Year:</strong> {1}</p>" + Environment.NewLine + "<p><strong>Copyright Year:</strong> {1}</p>" + Environment.NewLine +
"<p><strong>Approved:</strong> {2}</p>" + Environment.NewLine + "<p><strong>Approved:</strong> {2}</p>" + Environment.NewLine +