Reacting to Razor changes - TagHelperOutput is writing to TextWriter instead of string.

This commit is contained in:
sornaks 2015-02-23 14:35:12 -08:00
parent 81c3b75980
commit 284eb9ac6a
45 changed files with 825 additions and 801 deletions

View File

@ -1,177 +0,0 @@
// 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;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.Rendering
{
/// <summary>
/// Represents a hierarchy of strings and provides an enumerator that iterates over it as a sequence.
/// </summary>
public class BufferEntryCollection : IEnumerable<string>
{
// Specifies the maximum size we'll allow for direct conversion from
// char arrays to string.
private const int MaxCharToStringLength = 1024;
private readonly List<object> _buffer = new List<object>();
public IReadOnlyList<object> BufferEntries
{
get { return _buffer; }
}
/// <summary>
/// Adds a string value to the buffer.
/// </summary>
/// <param name="value">The value to add.</param>
public void Add(string value)
{
_buffer.Add(value);
}
/// <summary>
/// Adds a subarray of characters to the buffer.
/// </summary>
/// <param name="value">The array to add.</param>
/// <param name="index">The character position in the array at which to start copying data.</param>
/// <param name="count">The number of characters to copy.</param>
public void Add([NotNull] char[] value, int index, int count)
{
if (index < 0)
{
throw new ArgumentOutOfRangeException("index");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count");
}
if (value.Length - index < count)
{
throw new ArgumentOutOfRangeException("count");
}
while (count > 0)
{
// Split large char arrays into 1KB strings.
var currentCount = Math.Min(count, MaxCharToStringLength);
Add(new string(value, index, currentCount));
index += currentCount;
count -= currentCount;
}
}
/// <summary>
/// Adds an instance of <see cref="BufferEntryCollection"/> to the buffer.
/// </summary>
/// <param name="buffer">The buffer collection to add.</param>
public void Add([NotNull] BufferEntryCollection buffer)
{
_buffer.Add(buffer.BufferEntries);
}
/// <inheritdoc />
public IEnumerator<string> GetEnumerator()
{
return new BufferEntryEnumerator(_buffer);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private sealed class BufferEntryEnumerator : IEnumerator<string>
{
private readonly Stack<IEnumerator<object>> _enumerators = new Stack<IEnumerator<object>>();
private readonly List<object> _initialBuffer;
public BufferEntryEnumerator(List<object> buffer)
{
_initialBuffer = buffer;
Reset();
}
public IEnumerator<object> CurrentEnumerator
{
get
{
return _enumerators.Peek();
}
}
public string Current
{
get
{
var currentEnumerator = CurrentEnumerator;
Debug.Assert(currentEnumerator != null);
return (string)currentEnumerator.Current;
}
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public bool MoveNext()
{
var currentEnumerator = CurrentEnumerator;
if (currentEnumerator.MoveNext())
{
var current = currentEnumerator.Current;
var buffer = current as List<object>;
if (buffer != null)
{
// If the next item is a collection, recursively call in to it.
var enumerator = buffer.GetEnumerator();
_enumerators.Push(enumerator);
return MoveNext();
}
return true;
}
else if (_enumerators.Count > 1)
{
// The current enumerator is exhausted and we have a parent.
// Pop the current enumerator out and continue with it's parent.
var enumerator = _enumerators.Pop();
enumerator.Dispose();
return MoveNext();
}
// We've exactly one element in our stack which cannot move next.
return false;
}
public void Reset()
{
DisposeEnumerators();
_enumerators.Push(_initialBuffer.GetEnumerator());
}
public void Dispose()
{
DisposeEnumerators();
}
private void DisposeEnumerators()
{
while (_enumerators.Count > 0)
{
_enumerators.Pop().Dispose();
}
}
}
}
}

View File

@ -40,7 +40,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <summary>
/// A collection of entries buffered by this instance of <see cref="StringCollectionTextWriter"/>.
/// </summary>
public BufferEntryCollection Buffer { get; private set; }
// internal for testing purposes.
internal BufferEntryCollection Buffer { get; }
/// <inheritdoc />
public override void Write(char value)

View File

@ -15,6 +15,7 @@
"Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" },
"Microsoft.AspNet.Mvc.ModelBinding": "6.0.0-*",
"Microsoft.AspNet.Routing": "1.0.0-*",
"Microsoft.Framework.BufferEntryCollection.Internal": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.CopyOnWriteDictionary.Internal": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.NotNullAttribute.Internal": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.PropertyActivator.Internal": { "version": "1.0.0-*", "type": "build" },

View File

@ -98,8 +98,8 @@ namespace Microsoft.AspNet.Mvc.Razor
// Can't use nameof because RazorPage is not accessible here.
CreateTagHelperMethodName = "CreateTagHelper",
StartWritingScopeMethodName = "StartWritingScope",
EndWritingScopeMethodName = "EndWritingScope",
StartTagHelperWritingScopeMethodName = "StartTagHelperWritingScope",
EndTagHelperWritingScopeMethodName = "EndTagHelperWritingScope",
HtmlEncoderPropertyName = "HtmlEncoder",
})
{

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Rendering;
@ -159,11 +160,11 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary>
/// <remarks>
/// All writes to the <see cref="Output"/> or <see cref="ViewContext.Writer"/> after calling this method will
/// be buffered until <see cref="EndWritingScope"/> is called.
/// be buffered until <see cref="EndTagHelperWritingScope"/> is called.
/// </remarks>
public void StartWritingScope()
public void StartTagHelperWritingScope()
{
StartWritingScope(new StringWriter());
StartTagHelperWritingScope(new StringCollectionTextWriter(Output.Encoding));
}
/// <summary>
@ -171,9 +172,9 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary>
/// <remarks>
/// All writes to the <see cref="Output"/> or <see cref="ViewContext.Writer"/> after calling this method will
/// be buffered until <see cref="EndWritingScope"/> is called.
/// be buffered until <see cref="EndTagHelperWritingScope"/> is called.
/// </remarks>
public void StartWritingScope(TextWriter writer)
public void StartTagHelperWritingScope(TextWriter writer)
{
// If there isn't a base writer take the ViewContext.Writer
if (_originalWriter == null)
@ -189,11 +190,11 @@ namespace Microsoft.AspNet.Mvc.Razor
}
/// <summary>
/// Ends the current writing scope that was started by calling <see cref="StartWritingScope"/>.
/// Ends the current writing scope that was started by calling <see cref="StartTagHelperWritingScope"/>.
/// </summary>
/// <returns>The <see cref="TextWriter"/> that contains the content written to the <see cref="Output"/> or
/// <see cref="ViewContext.Writer"/> during the writing scope.</returns>
public TextWriter EndWritingScope()
public TagHelperContent EndTagHelperWritingScope()
{
if (_writerScopes.Count == 0)
{
@ -214,7 +215,49 @@ namespace Microsoft.AspNet.Mvc.Razor
_originalWriter = null;
}
return writer;
var tagHelperContentWrapperTextWriter = new TagHelperContentWrapperTextWriter(Output.Encoding);
var razorWriter = writer as RazorTextWriter;
if (razorWriter != null)
{
razorWriter.CopyTo(tagHelperContentWrapperTextWriter);
}
else
{
var stringCollectionTextWriter = writer as StringCollectionTextWriter;
if (stringCollectionTextWriter != null)
{
stringCollectionTextWriter.CopyTo(tagHelperContentWrapperTextWriter);
}
else
{
tagHelperContentWrapperTextWriter.Write(writer.ToString());
}
}
return tagHelperContentWrapperTextWriter.Content;
}
/// <summary>
/// Writes an <see cref="ITextWriterCopyable"/> to the <see cref="Output"/>.
/// </summary>
/// <param name="copyableTextWriter">Contains the data to be written.</param>
public void Write(ITextWriterCopyable copyableTextWriter)
{
WriteTo(Output, copyableTextWriter);
}
/// <summary>
/// Writes an <see cref="ITextWriterCopyable"/> to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="TextWriter"/> to which the
/// <paramref name="copyableTextWriter"/> is written.</param>
/// <param name="copyableTextWriter">Contains the data to be written.</param>
public void WriteTo(TextWriter writer, ITextWriterCopyable copyableTextWriter)
{
if (copyableTextWriter != null)
{
copyableTextWriter.CopyTo(writer);
}
}
/// <summary>
@ -649,5 +692,33 @@ namespace Microsoft.AspNet.Mvc.Razor
throw new InvalidOperationException(Resources.FormatRazorPage_MethodCannotBeCalled(methodName));
}
}
private class TagHelperContentWrapperTextWriter : TextWriter
{
public TagHelperContentWrapperTextWriter(Encoding encoding)
{
Content = new DefaultTagHelperContent();
Encoding = encoding;
}
public TagHelperContent Content { get; }
public override Encoding Encoding { get; }
public override void Write(string value)
{
Content.Append(value);
}
public override void Write(char value)
{
Content.Append(value.ToString());
}
public override string ToString()
{
return Content.ToString();
}
}
}
}

View File

@ -112,7 +112,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var key = GenerateKey(context);
string result;
TagHelperContent result;
if (!MemoryCache.TryGetValue(key, out result))
{
// Create an EntryLink and flow it so that it is accessible via the ambient EntryLinkHelpers.ContentLink
@ -132,8 +132,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Clear the contents of the "cache" element since we don't want to render it.
output.SuppressOutput();
output.Content = result;
output.Content.SetContent(result);
}
// Internal for unit testing

View File

@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
if (tagBuilder != null)
{
output.MergeAttributes(tagBuilder);
output.PostContent += tagBuilder.InnerHtml;
output.PostContent.Append(tagBuilder.InnerHtml);
}
}
@ -113,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var antiForgeryTagBuilder = Generator.GenerateAntiForgery(ViewContext);
if (antiForgeryTagBuilder != null)
{
output.PostContent += antiForgeryTagBuilder.ToString(TagRenderMode.SelfClosing);
output.PostContent.Append(antiForgeryTagBuilder.ToString(TagRenderMode.SelfClosing));
}
}
}

View File

@ -206,7 +206,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// This TagBuilder contains the one <input/> element of interest. Since this is not the "checkbox"
// special-case, output is a self-closing element no longer guarunteed.
output.MergeAttributes(tagBuilder);
output.Content += tagBuilder.InnerHtml;
output.Content.Append(tagBuilder.InnerHtml);
}
}
}
@ -242,12 +242,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
output.Attributes.Clear();
output.TagName = null;
output.Content += tagBuilder.ToString(TagRenderMode.SelfClosing);
output.Content.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
tagBuilder = Generator.GenerateHiddenForCheckbox(ViewContext, modelExplorer, For.Name);
if (tagBuilder != null)
{
output.Content += tagBuilder.ToString(TagRenderMode.SelfClosing);
output.Content.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
}
}
}

View File

@ -47,18 +47,18 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// We check for whitespace to detect scenarios such as:
// <label for="Name">
// </label>
if (!output.ContentSet)
if (!output.IsContentModified)
{
var childContent = await context.GetChildContentAsync();
if (string.IsNullOrWhiteSpace(childContent))
if (childContent.IsWhiteSpace)
{
// Provide default label text since there was nothing useful in the Razor source.
output.Content = tagBuilder.InnerHtml;
output.Content.SetContent(tagBuilder.InnerHtml);
}
else
{
output.Content = childContent;
output.Content.SetContent(childContent);
}
}
}

View File

@ -1,6 +1,7 @@
// 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;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@ -175,7 +176,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// NOTE: Values in TagHelperOutput.Attributes are already HtmlEncoded
var attributes = new Dictionary<string, string>(output.Attributes);
var builder = new StringBuilder();
var builder = new DefaultTagHelperContent();
if (mode == Mode.Fallback && string.IsNullOrEmpty(HrefInclude))
{
@ -194,10 +195,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// We've taken over tag rendering, so prevent rendering the outer tag
output.TagName = null;
output.Content = builder.ToString();
output.Content.SetContent(builder);
}
private void BuildGlobbedLinkTags(IDictionary<string, string> attributes, StringBuilder builder)
private void BuildGlobbedLinkTags(IDictionary<string, string> attributes, TagHelperContent builder)
{
// Build a <link /> tag for each matched href as well as the original one in the source file
string staticHref;
@ -213,30 +214,30 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
}
private void BuildFallbackBlock(StringBuilder builder)
private void BuildFallbackBlock(TagHelperContent builder)
{
EnsureGlobbingUrlBuilder();
var fallbackHrefs = GlobbingUrlBuilder.BuildUrlList(FallbackHref, FallbackHrefInclude, FallbackHrefExclude);
if (fallbackHrefs.Any())
{
builder.AppendLine();
builder.Append(Environment.NewLine);
// Build the <meta /> tag that's used to test for the presence of the stylesheet
builder.AppendFormat(
builder.Append(string.Format(
CultureInfo.InvariantCulture,
"<meta name=\"x-stylesheet-fallback-test\" class=\"{0}\" />",
HtmlEncoder.HtmlEncode(FallbackTestClass));
HtmlEncoder.HtmlEncode(FallbackTestClass)));
// 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,
// indicating that the primary stylesheet failed to load.
builder.Append("<script>")
.AppendFormat(CultureInfo.InvariantCulture,
.Append(string.Format(CultureInfo.InvariantCulture,
JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName),
JavaScriptStringEncoder.Default.JavaScriptStringEncode(FallbackTestProperty),
JavaScriptStringEncoder.Default.JavaScriptStringEncode(FallbackTestValue),
JavaScriptStringArrayEncoder.Encode(JavaScriptStringEncoder.Default, fallbackHrefs))
JavaScriptStringArrayEncoder.Encode(JavaScriptStringEncoder.Default, fallbackHrefs)))
.Append("</script>");
}
}
@ -252,13 +253,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
}
private static void BuildLinkTag(IDictionary<string, string> attributes, StringBuilder builder)
private static void BuildLinkTag(IDictionary<string, string> attributes, TagHelperContent builder)
{
builder.Append("<link ");
foreach (var attribute in attributes)
{
builder.AppendFormat(CultureInfo.InvariantCulture, "{0}=\"{1}\" ", attribute.Key, attribute.Value);
builder.Append(
string.Format(CultureInfo.InvariantCulture, "{0}=\"{1}\" ", attribute.Key, attribute.Value));
}
builder.Append("/>");

View File

@ -86,8 +86,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Select this <option/> element if value attribute or content matches a selected value. Callers
// encode values as-needed while executing child content. But TagHelperOutput itself
// encodes attribute values later, when GenerateStartTag() is called.
var text = await context.GetChildContentAsync();
var selected = (Value != null) ? selectedValues.Contains(Value) : encodedValues.Contains(text);
bool selected;
if (Value != null)
{
selected = selectedValues.Contains(Value);
}
else
{
var childContent = await context.GetChildContentAsync();
selected = encodedValues.Contains(childContent.GetContent());
}
if (selected)
{
output.Attributes.Add("selected", "selected");

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Mvc.TagHelpers.Internal;
@ -155,7 +154,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// NOTE: Values in TagHelperOutput.Attributes are already HtmlEncoded
var attributes = new Dictionary<string, string>(output.Attributes);
var builder = new StringBuilder();
var builder = new DefaultTagHelperContent();
var originalContent = await context.GetChildContentAsync();
if (mode == Mode.Fallback && string.IsNullOrEmpty(SrcInclude))
@ -175,13 +174,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// We've taken over tag rendering, so prevent rendering the outer tag
output.TagName = null;
output.Content = builder.ToString();
output.Content.SetContent(builder);
}
private void BuildGlobbedScriptTags(
string originalContent,
TagHelperContent originalContent,
IDictionary<string, string> attributes,
StringBuilder builder)
TagHelperContent builder)
{
// Build a <script> tag for each matched src as well as the original one in the source file
string staticSrc;
@ -193,14 +192,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
foreach (var url in urls)
{
attributes["src"] = HtmlEncoder.HtmlEncode(url);
var content = string.Equals(url, staticSrc, StringComparison.OrdinalIgnoreCase)
? originalContent
: string.Empty;
var content =
string.Equals(url, staticSrc, StringComparison.OrdinalIgnoreCase) ? originalContent : null;
BuildScriptTag(content, attributes, builder);
}
}
private void BuildFallbackBlock(IDictionary<string, string> attributes, StringBuilder builder)
private void BuildFallbackBlock(IDictionary<string, string> attributes, DefaultTagHelperContent builder)
{
EnsureGlobbingUrlBuilder();
@ -209,7 +207,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
if (fallbackSrcs.Any())
{
// Build the <script> tag that checks the test method and if it fails, renders the extra script.
builder.AppendLine()
builder.Append(Environment.NewLine)
.Append("<script>(")
.Append(FallbackTestExpression)
.Append("||document.write(\"");
@ -230,11 +228,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var encodedKey = JavaScriptStringEncoder.Default.JavaScriptStringEncode(attribute.Key);
var encodedValue = JavaScriptStringEncoder.Default.JavaScriptStringEncode(attribute.Value);
builder.AppendFormat(
builder.Append(string.Format(
CultureInfo.InvariantCulture,
" {0}=\\\"{1}\\\"",
encodedKey,
encodedValue);
encodedValue));
}
else
{
@ -261,15 +259,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
private static void BuildScriptTag(
string content,
TagHelperContent content,
IDictionary<string, string> attributes,
StringBuilder builder)
TagHelperContent builder)
{
builder.Append("<script");
foreach (var attribute in attributes)
{
builder.AppendFormat(CultureInfo.InvariantCulture, " {0}=\"{1}\"", attribute.Key, attribute.Value);
builder.Append(
string.Format(CultureInfo.InvariantCulture, " {0}=\"{1}\"", attribute.Key, attribute.Value));
}
builder.Append(">")
@ -277,7 +276,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Append("</script>");
}
private void AppendSrc(StringBuilder content, string srcKey, string srcValue)
private void AppendSrc(TagHelperContent content, string srcKey, string srcValue)
{
// Append src attribute in the original place and replace the content the fallback content
// No need to encode the key because we know it is "src".

View File

@ -107,7 +107,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
if (tagBuilder != null)
{
output.MergeAttributes(tagBuilder);
output.PostContent += tagBuilder.InnerHtml;
output.PostContent.Append(tagBuilder.InnerHtml);
}
// Whether or not (not being highly unlikely) we generate anything, could update contained <option/>

View File

@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
if (tagBuilder != null)
{
// Overwrite current Content to ensure expression result round-trips correctly.
output.Content = tagBuilder.InnerHtml;
output.Content.SetContent(tagBuilder.InnerHtml);
output.MergeAttributes(tagBuilder);
}

View File

@ -49,18 +49,18 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// We check for whitespace to detect scenarios such as:
// <span validation-for="Name">
// </span>
if (!output.ContentSet)
if (!output.IsContentModified)
{
var childContent = await context.GetChildContentAsync();
if (string.IsNullOrWhiteSpace(childContent))
if (childContent.IsWhiteSpace)
{
// Provide default label text since there was nothing useful in the Razor source.
output.Content = tagBuilder.InnerHtml;
output.Content.SetContent(tagBuilder.InnerHtml);
}
else
{
output.Content = childContent;
output.Content.SetContent(childContent);
}
}
}

View File

@ -4,7 +4,6 @@
using System;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Razor.TagHelpers;
namespace Microsoft.AspNet.Mvc.TagHelpers
{
@ -80,7 +79,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
if (tagBuilder != null)
{
output.MergeAttributes(tagBuilder);
output.PostContent += tagBuilder.InnerHtml;
output.PostContent.Append(tagBuilder.InnerHtml);
}
}
}

View File

@ -1,160 +0,0 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace Microsoft.AspNet.Mvc.Rendering
{
public class BufferEntryCollectionTest
{
[Fact]
public void Add_AddsBufferEntries()
{
// Arrange
var collection = new BufferEntryCollection();
var inner = new BufferEntryCollection();
// Act
collection.Add("Hello");
collection.Add(new[] { 'a', 'b', 'c' }, 1, 2);
collection.Add(inner);
// Assert
Assert.Equal("Hello", collection.BufferEntries[0]);
Assert.Equal("bc", collection.BufferEntries[1]);
Assert.Same(inner.BufferEntries, collection.BufferEntries[2]);
}
[Fact]
public void AddChar_ThrowsIfIndexIsOutOfBounds()
{
// Arrange
var collection = new BufferEntryCollection();
// Act and Assert
var ex = Assert.Throws<ArgumentOutOfRangeException>(
() => collection.Add(new[] { 'a', 'b', 'c' }, -1, 2));
Assert.Equal("index", ex.ParamName);
}
[Fact]
public void AddChar_ThrowsIfCountWouldCauseOutOfBoundReads()
{
// Arrange
var collection = new BufferEntryCollection();
// Act and Assert
var ex = Assert.Throws<ArgumentOutOfRangeException>(
() => collection.Add(new[] { 'a', 'b', 'c' }, 1, 3));
Assert.Equal("count", ex.ParamName);
}
public static IEnumerable<object[]> AddWithChar_RepresentsStringsAsChunkedEntriesData
{
get
{
var charArray1 = new[] { 'a' };
var expected1 = new[] { "a" };
yield return new object[] { charArray1, 0, 1, expected1 };
var charArray2 = Enumerable.Repeat('a', 10).ToArray();
var expected2 = new[] { new string(charArray2) };
yield return new object[] { charArray2, 0, 10, expected2 };
var charArray3 = Enumerable.Repeat('b', 1024).ToArray();
var expected3 = new[] { new string('b', 1023) };
yield return new object[] { charArray3, 1, 1023, expected3 };
var charArray4 = Enumerable.Repeat('c', 1027).ToArray();
var expected4 = new[] { new string('c', 1024), "cc" };
yield return new object[] { charArray4, 1, 1026, expected4 };
var charArray5 = Enumerable.Repeat('d', 4099).ToArray();
var expected5 = new[] { new string('d', 1024), new string('d', 1024), new string('d', 1024), new string('d', 1024), "d" };
yield return new object[] { charArray5, 2, 4097, expected5 };
var charArray6 = Enumerable.Repeat('e', 1025).ToArray();
var expected6 = new[] { "ee" };
yield return new object[] { charArray6, 1023, 2, expected6 };
}
}
[Theory]
[MemberData(nameof(AddWithChar_RepresentsStringsAsChunkedEntriesData))]
public void AddWithChar_RepresentsStringsAsChunkedEntries(char[] value, int index, int count, IList<object> expected)
{
// Arrange
var collection = new BufferEntryCollection();
// Act
collection.Add(value, index, count);
// Assert
Assert.Equal(expected, collection.BufferEntries);
}
public static IEnumerable<object[]> Enumerator_TraversesThroughBufferData
{
get
{
var collection1 = new BufferEntryCollection();
collection1.Add("foo");
collection1.Add("bar");
var expected1 = new[]
{
"foo",
"bar"
};
yield return new object[] { collection1, expected1 };
// Nested collection
var nestedCollection2 = new BufferEntryCollection();
nestedCollection2.Add("level 1");
var nestedCollection2SecondLevel = new BufferEntryCollection();
nestedCollection2SecondLevel.Add("level 2");
nestedCollection2.Add(nestedCollection2SecondLevel);
var collection2 = new BufferEntryCollection();
collection2.Add("foo");
collection2.Add(nestedCollection2);
collection2.Add("qux");
var expected2 = new[]
{
"foo",
"level 1",
"level 2",
"qux"
};
yield return new object[] { collection2, expected2 };
// Nested collection
var collection3 = new BufferEntryCollection();
collection3.Add("Hello");
var emptyNestedCollection = new BufferEntryCollection();
emptyNestedCollection.Add(new BufferEntryCollection());
collection3.Add(emptyNestedCollection);
collection3.Add("world");
var expected3 = new[]
{
"Hello",
"world"
};
yield return new object[] { collection3, expected3 };
}
}
[Theory]
[MemberData(nameof(Enumerator_TraversesThroughBufferData))]
public void Enumerator_TraversesThroughBuffer(BufferEntryCollection buffer, string[] expected)
{
// Act and Assert
Assert.Equal(expected, buffer);
}
}
}

View File

@ -19,7 +19,7 @@ namespace Asp
{
#line hidden
#pragma warning disable 0414
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
private TagHelperContent __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext = null;
private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = null;
@ -48,7 +48,7 @@ namespace Asp
EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", true, "test", async() => {
}
, StartWritingScope, EndWritingScope);
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = CreateTagHelper<Microsoft.AspNet.Mvc.Razor.InputTestTagHelper>();
__tagHelperExecutionContext.Add(__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper);
#line 5 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
@ -59,20 +59,20 @@ __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__mo
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For);
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
if (__tagHelperExecutionContext.Output.ContentSet)
Write(__tagHelperExecutionContext.Output.GeneratePreContent());
if (__tagHelperExecutionContext.Output.IsContentModified)
{
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
Write(__tagHelperExecutionContext.Output.GenerateContent());
}
else if (__tagHelperExecutionContext.ChildContentRetrieved)
{
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
Write(__tagHelperExecutionContext.GetChildContentAsync().Result);
}
else
{
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
}
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
Write(__tagHelperExecutionContext.Output.GeneratePostContent());
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
__tagHelperExecutionContext = __tagHelperScopeManager.End();
BeginContext(146, 2, true);
@ -80,7 +80,7 @@ __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__mo
EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", true, "test", async() => {
}
, StartWritingScope, EndWritingScope);
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = CreateTagHelper<Microsoft.AspNet.Mvc.Razor.InputTestTagHelper>();
__tagHelperExecutionContext.Add(__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper);
#line 6 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
@ -91,20 +91,20 @@ __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__mo
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For);
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
if (__tagHelperExecutionContext.Output.ContentSet)
Write(__tagHelperExecutionContext.Output.GeneratePreContent());
if (__tagHelperExecutionContext.Output.IsContentModified)
{
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
Write(__tagHelperExecutionContext.Output.GenerateContent());
}
else if (__tagHelperExecutionContext.ChildContentRetrieved)
{
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
Write(__tagHelperExecutionContext.GetChildContentAsync().Result);
}
else
{
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
}
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
Write(__tagHelperExecutionContext.Output.GeneratePostContent());
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
__tagHelperExecutionContext = __tagHelperScopeManager.End();
}

View File

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Testing;
using Microsoft.Framework.WebEncoders;
using Moq;
@ -31,10 +32,10 @@ namespace Microsoft.AspNet.Mvc.Razor
{
v.HtmlEncoder = new HtmlEncoder();
v.Write("Hello Prefix");
v.StartWritingScope();
v.StartTagHelperWritingScope();
v.Write("Hello from Output");
v.ViewContext.Writer.Write("Hello from view context writer");
var scopeValue = v.EndWritingScope();
var scopeValue = v.EndTagHelperWritingScope();
v.Write("From Scope: " + scopeValue.ToString());
});
@ -55,9 +56,9 @@ namespace Microsoft.AspNet.Mvc.Razor
{
v.HtmlEncoder = new HtmlEncoder();
v.Write("Hello Prefix");
v.StartWritingScope();
v.StartTagHelperWritingScope();
v.Write("Hello In Scope");
var scopeValue = v.EndWritingScope();
var scopeValue = v.EndTagHelperWritingScope();
v.Write("From Scope: " + scopeValue.ToString());
});
@ -78,15 +79,15 @@ namespace Microsoft.AspNet.Mvc.Razor
{
v.HtmlEncoder = new HtmlEncoder();
v.Write("Hello Prefix");
v.StartWritingScope();
v.StartTagHelperWritingScope();
v.Write("Hello In Scope Pre Nest");
v.StartWritingScope();
v.StartTagHelperWritingScope();
v.Write("Hello In Nested Scope");
var scopeValue1 = v.EndWritingScope();
var scopeValue1 = v.EndTagHelperWritingScope();
v.Write("Hello In Scope Post Nest");
var scopeValue2 = v.EndWritingScope();
var scopeValue2 = v.EndTagHelperWritingScope();
v.Write("From Scopes: " + scopeValue2.ToString() + scopeValue1.ToString());
});
@ -106,7 +107,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var viewContext = CreateViewContext();
var page = CreatePage(async v =>
{
v.StartWritingScope();
v.StartTagHelperWritingScope();
await v.FlushAsync();
});
@ -125,7 +126,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var viewContext = CreateViewContext();
var page = CreatePage(v =>
{
v.EndWritingScope();
v.EndTagHelperWritingScope();
});
// Act
@ -136,6 +137,50 @@ namespace Microsoft.AspNet.Mvc.Razor
Assert.Equal("There is no active writing scope to end.", ex.Message);
}
[Fact]
public async Task EndTagHelperWritingScope_ReturnsAppropriateContent()
{
// Arrange
var viewContext = CreateViewContext();
// Act
var page = CreatePage(v =>
{
v.HtmlEncoder = new HtmlEncoder();
v.StartTagHelperWritingScope();
v.Write("Hello World!");
var returnValue = v.EndTagHelperWritingScope();
// Assert
var content = Assert.IsType<DefaultTagHelperContent>(returnValue);
Assert.Equal("Hello World!", content.GetContent());
});
await page.ExecuteAsync();
}
[Fact]
public async Task EndTagHelperWritingScope_CopiesContent_IfRazorTextWriter()
{
// Arrange
var viewContext = CreateViewContext();
// Act
var page = CreatePage(v =>
{
v.HtmlEncoder = new HtmlEncoder();
v.StartTagHelperWritingScope(new RazorTextWriter(TextWriter.Null, Encoding.UTF8));
v.Write("Hello ");
v.Write("World!");
var returnValue = v.EndTagHelperWritingScope();
// Assert
var content = Assert.IsType<DefaultTagHelperContent>(returnValue);
Assert.Equal("Hello World!", content.GetContent());
Assert.Equal(new[] { "Hello ", "World!" }, content.AsArray());
}, viewContext);
await page.ExecuteAsync();
}
[Fact]
public async Task DefineSection_ThrowsIfSectionIsAlreadyDefined()
{
@ -642,6 +687,72 @@ namespace Microsoft.AspNet.Mvc.Razor
Assert.Same(stringCollectionWriter.Buffer.BufferEntries, buffer.BufferEntries[1]);
}
[Fact]
public async Task Write_ITextWriterCopyable_WritesContent()
{
// Arrange
// This writer uses BufferEntryCollection underneath and so can copy the buffer.
var writer = new StringCollectionTextWriter(Encoding.UTF8);
var context = CreateViewContext(writer);
var expectedContent = "Hello World!";
var contentToBeCopied = new DefaultTagHelperContent().SetContent("Hello ").Append("World!");
// Act
var page = CreatePage(p =>
{
p.Write((ITextWriterCopyable)contentToBeCopied);
}, context);
await page.ExecuteAsync();
// Assert
Assert.Equal(expectedContent, writer.ToString());
Assert.Equal(2, writer.Buffer.BufferEntries.Count);
var expectedList = new List<object>();
expectedList.Add("Hello ");
expectedList.Add("World!");
Assert.Equal(expectedList, writer.Buffer.BufferEntries);
}
[Fact]
public async Task Write_ITextWriterCopyable_WritesContent_AsString()
{
// Arrange
// This writer stores the data as a string.
var writer = new StringWriter();
var context = CreateViewContext(writer);
var expectedContent = "Hello World!";
var contentToBeCopied = new DefaultTagHelperContent().SetContent("Hello ").Append("World!");
// Act
var page = CreatePage(p =>
{
p.Write((ITextWriterCopyable)contentToBeCopied);
}, context);
await page.ExecuteAsync();
// Assert
Assert.Equal(expectedContent, writer.ToString());
}
[Fact]
public async Task WriteTo_ITextWriterCopyable_WritesContent_ToSpecifiedWriter()
{
// Arrange
var writer = new StringWriter();
var expectedContent = "Hello World!";
var contentToBeCopied = new DefaultTagHelperContent().SetContent("Hello ").Append("World!");
// Act
var page = CreatePage(p =>
{
p.WriteTo(writer, (ITextWriterCopyable)contentToBeCopied);
});
await page.ExecuteAsync();
// Assert
Assert.Equal(expectedContent, writer.ToString());
}
private static TestableRazorPage CreatePage(Action<TestableRazorPage> executeAction,
ViewContext context = null)
{

View File

@ -35,7 +35,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something Else"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something Else");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, string>
@ -43,10 +48,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ "id", "myanchor" },
{ "asp-route-foo", "bar" },
},
htmlEncoder: new HtmlEncoder())
{
Content = "Something"
};
htmlEncoder: new HtmlEncoder());
output.Content.SetContent("Something");
var urlHelper = new Mock<IUrlHelper>();
urlHelper
@ -75,7 +78,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("myanchor", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("href"));
Assert.Equal("home/index", attribute.Value);
Assert.Equal("Something", output.Content);
Assert.Equal("Something", output.Content.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -87,14 +90,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
"a",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
Content = string.Empty
};
htmlEncoder: new HtmlEncoder());
output.Content.SetContent(string.Empty);
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
generator
@ -116,7 +122,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator.Verify();
Assert.Equal("a", output.TagName);
Assert.Empty(output.Attributes);
Assert.Empty(output.Content);
Assert.True(output.Content.IsEmpty);
}
[Fact]
@ -127,14 +133,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
"a",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
Content = string.Empty
};
htmlEncoder: new HtmlEncoder());
output.Content.SetContent(string.Empty);
var generator = new Mock<IHtmlGenerator>();
generator
@ -157,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator.Verify();
Assert.Equal("a", output.TagName);
Assert.Empty(output.Attributes);
Assert.Empty(output.Content);
Assert.True(output.Content.IsEmpty);
}
[Theory]

View File

@ -259,10 +259,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);
// Assert - 1
Assert.Null(tagHelperOutput1.PreContent);
Assert.Null(tagHelperOutput1.PostContent);
Assert.True(tagHelperOutput1.ContentSet);
Assert.Equal(childContent, tagHelperOutput1.Content);
Assert.Empty(tagHelperOutput1.PreContent.GetContent());
Assert.Empty(tagHelperOutput1.PostContent.GetContent());
Assert.True(tagHelperOutput1.IsContentModified);
Assert.Equal(childContent, tagHelperOutput1.Content.GetContent());
// Arrange - 2
var tagHelperContext2 = GetTagHelperContext(id, "different-content");
@ -280,10 +280,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
// Assert - 2
Assert.Null(tagHelperOutput2.PreContent);
Assert.Null(tagHelperOutput2.PostContent);
Assert.True(tagHelperOutput2.ContentSet);
Assert.Equal(childContent, tagHelperOutput2.Content);
Assert.Empty(tagHelperOutput2.PreContent.GetContent());
Assert.Empty(tagHelperOutput2.PostContent.GetContent());
Assert.True(tagHelperOutput2.IsContentModified);
Assert.Equal(childContent, tagHelperOutput2.Content.GetContent());
}
[Fact]
@ -296,11 +296,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput1.PreContent.Append("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
{
VaryByCookie = "cookie1,cookie2",
@ -313,21 +311,20 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);
// Assert - 1
Assert.Null(tagHelperOutput1.PreContent);
Assert.Null(tagHelperOutput1.PostContent);
Assert.True(tagHelperOutput1.ContentSet);
Assert.Equal(childContent1, tagHelperOutput1.Content);
Assert.Empty(tagHelperOutput1.PreContent.GetContent());
Assert.Empty(tagHelperOutput1.PostContent.GetContent());
Assert.True(tagHelperOutput1.IsContentModified);
Assert.Equal(childContent1, tagHelperOutput1.Content.GetContent());
// Arrange - 2
var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
var tagHelperOutput2 = new TagHelperOutput(
"cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder());
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
{
VaryByCookie = "cookie1,cookie2",
@ -340,10 +337,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
// Assert - 2
Assert.Null(tagHelperOutput2.PreContent);
Assert.Null(tagHelperOutput2.PostContent);
Assert.True(tagHelperOutput2.ContentSet);
Assert.Equal(childContent2, tagHelperOutput2.Content);
Assert.Empty(tagHelperOutput2.PreContent.GetContent());
Assert.Empty(tagHelperOutput2.PostContent.GetContent());
Assert.True(tagHelperOutput2.IsContentModified);
Assert.Equal(childContent2, tagHelperOutput2.Content.GetContent());
}
[Fact]
@ -536,11 +533,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput1.PreContent.SetContent("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -552,21 +547,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);
// Assert - 1
Assert.Null(tagHelperOutput1.PreContent);
Assert.Null(tagHelperOutput1.PostContent);
Assert.True(tagHelperOutput1.ContentSet);
Assert.Equal(childContent1, tagHelperOutput1.Content);
Assert.Empty(tagHelperOutput1.PreContent.GetContent());
Assert.Empty(tagHelperOutput1.PostContent.GetContent());
Assert.True(tagHelperOutput1.IsContentModified);
Assert.Equal(childContent1, tagHelperOutput1.Content.GetContent());
// Arrange - 2
var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -579,10 +572,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
// Assert - 2
Assert.Null(tagHelperOutput2.PreContent);
Assert.Null(tagHelperOutput2.PostContent);
Assert.True(tagHelperOutput2.ContentSet);
Assert.Equal(childContent2, tagHelperOutput2.Content);
Assert.Empty(tagHelperOutput2.PreContent.GetContent());
Assert.Empty(tagHelperOutput2.PostContent.GetContent());
Assert.True(tagHelperOutput2.IsContentModified);
Assert.Equal(childContent2, tagHelperOutput2.Content.GetContent());
}
[Fact]
@ -599,11 +592,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput1.PreContent.SetContent("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -615,10 +606,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);
// Assert - 1
Assert.Null(tagHelperOutput1.PreContent);
Assert.Null(tagHelperOutput1.PostContent);
Assert.True(tagHelperOutput1.ContentSet);
Assert.Equal(childContent1, tagHelperOutput1.Content);
Assert.Empty(tagHelperOutput1.PreContent.GetContent());
Assert.Empty(tagHelperOutput1.PostContent.GetContent());
Assert.True(tagHelperOutput1.IsContentModified);
Assert.Equal(childContent1, tagHelperOutput1.Content.GetContent());
// Arrange - 2
currentTime = currentTime.AddMinutes(5).AddSeconds(2);
@ -626,11 +617,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -642,10 +631,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
// Assert - 2
Assert.Null(tagHelperOutput2.PreContent);
Assert.Null(tagHelperOutput2.PostContent);
Assert.True(tagHelperOutput2.ContentSet);
Assert.Equal(childContent2, tagHelperOutput2.Content);
Assert.Empty(tagHelperOutput2.PreContent.GetContent());
Assert.Empty(tagHelperOutput2.PostContent.GetContent());
Assert.True(tagHelperOutput2.IsContentModified);
Assert.Equal(childContent2, tagHelperOutput2.Content.GetContent());
}
[Fact]
@ -662,11 +651,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput1.PreContent.SetContent("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -678,10 +665,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);
// Assert - 1
Assert.Null(tagHelperOutput1.PreContent);
Assert.Null(tagHelperOutput1.PostContent);
Assert.True(tagHelperOutput1.ContentSet);
Assert.Equal(childContent1, tagHelperOutput1.Content);
Assert.Empty(tagHelperOutput1.PreContent.GetContent());
Assert.Empty(tagHelperOutput1.PostContent.GetContent());
Assert.True(tagHelperOutput1.IsContentModified);
Assert.Equal(childContent1, tagHelperOutput1.Content.GetContent());
// Arrange - 2
currentTime = currentTime.AddSeconds(35);
@ -689,11 +676,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -705,10 +690,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
// Assert - 2
Assert.Null(tagHelperOutput2.PreContent);
Assert.Null(tagHelperOutput2.PostContent);
Assert.True(tagHelperOutput2.ContentSet);
Assert.Equal(childContent2, tagHelperOutput2.Content);
Assert.Empty(tagHelperOutput2.PreContent.GetContent());
Assert.Empty(tagHelperOutput2.PostContent.GetContent());
Assert.True(tagHelperOutput2.IsContentModified);
Assert.Equal(childContent2, tagHelperOutput2.Content.GetContent());
}
[Fact]
@ -716,7 +701,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var id = "some-id";
var expectedContent = "some-content";
var expectedContent = new DefaultTagHelperContent();
expectedContent.SetContent("some-content");
var tokenSource = new CancellationTokenSource();
var cache = new MemoryCache(new MemoryCacheOptions());
var tagHelperContext = new TagHelperContext(
@ -731,15 +717,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
new CancellationTokenTrigger(tokenSource.Token)
});
return Task.FromResult(expectedContent);
return Task.FromResult<TagHelperContent>(expectedContent);
});
var tagHelperOutput = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{
PreContent = "<cache>",
PostContent = "</cache>"
};
new HtmlEncoder());
tagHelperOutput.PreContent.SetContent("<cache>");
tagHelperOutput.PostContent.SetContent("</cache>");
var cacheTagHelper = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -749,11 +733,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Act - 1
await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);
string cachedValue;
TagHelperContent cachedValue;
var result = cache.TryGetValue(key, out cachedValue);
// Assert - 1
Assert.Equal(expectedContent, tagHelperOutput.Content);
Assert.Equal(expectedContent.GetContent(), tagHelperOutput.Content.GetContent());
Assert.True(result);
Assert.Equal(expectedContent, cachedValue);
@ -782,7 +766,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: id,
getChildContentAsync: () => Task.FromResult(childContent));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(childContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
}
private static string GetHashedBytes(string input)

View File

@ -98,10 +98,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
// Assert
Assert.Null(output.TagName);
Assert.Null(output.PreContent);
Assert.Null(output.Content);
Assert.Null(output.PostContent);
Assert.True(output.ContentSet);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Empty(output.PostContent.GetContent());
Assert.True(output.IsContentModified);
}
private void ShouldShowContent(string namesAttribute, string environmentName)
@ -126,7 +126,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
// Assert
Assert.Null(output.TagName);
Assert.False(output.ContentSet);
Assert.False(output.IsContentModified);
}
private TagHelperContext MakeTagHelperContext(
@ -139,7 +139,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
attributes,
items: new Dictionary<object, object>(),
uniqueId: Guid.NewGuid().ToString("N"),
getChildContentAsync: () => Task.FromResult(content));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(content);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
}
private TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, string> attributes = null)

View File

@ -36,7 +36,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something Else"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something Else");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, string>
@ -44,10 +49,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ "id", "myform" },
{ "asp-route-foo", "bar" },
},
htmlEncoder: new HtmlEncoder())
{
PostContent = "Something"
};
htmlEncoder: new HtmlEncoder());
output.PostContent.SetContent("Something");
var urlHelper = new Mock<IUrlHelper>();
urlHelper
.Setup(mock => mock.Action(It.IsAny<UrlActionContext>())).Returns("home/index");
@ -79,9 +82,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("post", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("action"));
Assert.Equal("home/index", attribute.Value);
Assert.Empty(output.PreContent);
Assert.Empty(output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -97,7 +100,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
"form",
attributes: new Dictionary<string, string>(),
@ -130,9 +138,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("form", output.TagName);
Assert.False(output.SelfClosing);
Assert.Empty(output.Attributes);
Assert.Empty(output.PreContent);
Assert.Empty(output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
}
[Fact]
@ -144,7 +152,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var expectedAttribute = new KeyValuePair<string, string>("asp-ROUTEE-NotRoute", "something");
var output = new TagHelperOutput(
"form",
@ -196,9 +209,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.False(output.SelfClosing);
var attribute = Assert.Single(output.Attributes);
Assert.Equal(expectedAttribute, attribute);
Assert.Empty(output.PreContent);
Assert.Empty(output.Content);
Assert.Empty(output.PostContent);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Empty(output.PostContent.GetContent());
generator.Verify();
}
@ -211,7 +224,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
"form",
attributes: new Dictionary<string, string>(),
@ -238,9 +256,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("form", output.TagName);
Assert.False(output.SelfClosing);
Assert.Empty(output.Attributes);
Assert.Empty(output.PreContent);
Assert.Empty(output.Content);
Assert.Empty(output.PostContent);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Empty(output.PostContent.GetContent());
}
[Theory]
@ -268,7 +286,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
// Act
await formTagHelper.ProcessAsync(context, output);
@ -280,9 +303,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal(htmlAction, attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("METhod"));
Assert.Equal("POST", attribute.Value);
Assert.Empty(output.PreContent);
Assert.Empty(output.Content);
Assert.Empty(output.PostContent);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Empty(output.PostContent.GetContent());
}
[Theory]
@ -316,7 +339,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
// Act
@ -327,9 +355,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.False(output.SelfClosing);
var attribute = Assert.Single(output.Attributes);
Assert.Equal(new KeyValuePair<string, string>("aCTiON", "my-action"), attribute);
Assert.Empty(output.PreContent);
Assert.Empty(output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
}
[Theory]

View File

@ -99,18 +99,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider())
{
@ -134,9 +139,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.False(output.SelfClosing);
Assert.Equal(expectedTagName, output.TagName);
}
@ -155,18 +160,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(originalTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = originalContent,
PostContent = expectedPostContent,
SelfClosing = true,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(originalContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model: false, propertyName: nameof(Model.IsACar));
@ -201,9 +211,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
htmlGenerator.Verify();
Assert.Empty(output.Attributes); // Moved to Content and cleared
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.True(output.SelfClosing);
Assert.Null(output.TagName); // Cleared
}
@ -246,18 +256,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
@ -290,9 +305,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.False(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -334,18 +349,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
@ -377,9 +397,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.False(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -419,18 +439,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
@ -463,9 +488,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.False(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -519,18 +544,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
@ -563,9 +593,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.False(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -588,14 +618,20 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, expectedAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider())
{
@ -612,9 +648,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.False(output.SelfClosing);
Assert.Equal(expectedTagName, output.TagName);
}
@ -644,7 +680,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder());
var tagHelper = new InputTagHelper
{

View File

@ -128,7 +128,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
attributes,
items: new Dictionary<object, object>(),
uniqueId: Guid.NewGuid().ToString("N"),
getChildContentAsync: () => Task.FromResult(content));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.Append(content);
return Task.FromResult((TagHelperContent)tagHelperContent);
});
}
}
}

View File

@ -190,22 +190,25 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult(tagHelperOutputContent.OriginalChildContent));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(tagHelperOutputContent.OriginalChildContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var htmlAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(expectedTagName, htmlAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
PostContent = expectedPostContent,
};
var output = new TagHelperOutput(expectedTagName, htmlAttributes, new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.PostContent.SetContent(expectedPostContent);
// LabelTagHelper checks ContentSet 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.
if (!string.IsNullOrEmpty(tagHelperOutputContent.OriginalContent))
{
output.Content = tagHelperOutputContent.OriginalContent;
output.Content.SetContent(tagHelperOutputContent.OriginalContent);
}
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
@ -218,9 +221,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(tagHelperOutputContent.ExpectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(tagHelperOutputContent.ExpectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.False(output.SelfClosing);
Assert.Equal(expectedTagName, output.TagName);
}
@ -250,13 +253,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, expectedAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
};
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, expectedAttributes, new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
Model model = null;
@ -269,9 +275,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}

View File

@ -114,7 +114,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Null(output.TagName);
Assert.NotNull(output.Content);
Assert.True(output.ContentSet);
Assert.True(output.IsContentModified);
}
[Fact]
@ -158,7 +158,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
helper.Process(context, output);
// Assert
Assert.StartsWith("<link rel=\"stylesheet\" data-extra=\"something\" href=\"test.css\"", output.Content);
Assert.StartsWith(
"<link rel=\"stylesheet\" data-extra=\"something\" href=\"test.css\"", output.Content.GetContent());
}
public static TheoryData DoesNotRunWhenARequiredAttributeIsMissing_Data
@ -258,7 +259,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.NotNull(output.TagName);
Assert.False(output.ContentSet);
Assert.False(output.IsContentModified);
}
[Fact]
@ -282,7 +283,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.NotNull(output.TagName);
Assert.False(output.ContentSet);
Assert.False(output.IsContentModified);
}
[Fact]
@ -322,7 +323,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("<link href=\"/css/site.css\" rel=\"stylesheet\" />" +
"<link href=\"/base.css\" rel=\"stylesheet\" />", output.Content);
"<link href=\"/base.css\" rel=\"stylesheet\" />", output.Content.GetContent());
}
[Fact]
@ -362,7 +363,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("<link href=\"HtmlEncode[[/css/site.css]]\" rel=\"stylesheet\" />" +
"<link href=\"HtmlEncode[[/base.css]]\" rel=\"stylesheet\" />", output.Content);
"<link href=\"HtmlEncode[[/base.css]]\" rel=\"stylesheet\" />", output.Content.GetContent());
}
private static ViewContext MakeViewContext()
@ -385,7 +386,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes,
items: new Dictionary<object, object>(),
uniqueId: Guid.NewGuid().ToString("N"),
getChildContentAsync: () => Task.FromResult(content));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(content);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
}
private static TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, string> attributes = null)

View File

@ -141,12 +141,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult(originalContent));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(originalContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
Content = originalContent,
SelfClosing = false,
};
output.Content.SetContent(originalContent);
var metadataProvider = new EmptyModelMetadataProvider();
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
@ -169,7 +174,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(
expectedOutput,
output.GenerateStartTag() + output.GenerateContent() + output.GenerateEndTag());
output.GenerateStartTag() +
(output.GenerateContent() as TagHelperContent).GetContent() +
output.GenerateEndTag());
}
[Theory]
@ -200,14 +207,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult(originalContent));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(originalContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(originalTagName, originalAttributes, new HtmlEncoder())
{
PreContent = originalPreContent,
Content = originalContent,
PostContent = originalPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(originalPreContent);
output.Content.SetContent(originalContent);
output.PostContent.SetContent(originalPostContent);
var metadataProvider = new EmptyModelMetadataProvider();
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
@ -256,14 +268,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult(originalContent));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(originalContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(originalTagName, originalAttributes, new HtmlEncoder())
{
PreContent = originalPreContent,
Content = originalContent,
PostContent = originalPostContent,
SelfClosing = false,
};
output.PreContent.SetContent(originalPreContent);
output.Content.SetContent(originalContent);
output.PostContent.SetContent(originalPostContent);
var tagHelper = new OptionTagHelper
{

View File

@ -133,8 +133,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Null(output.TagName);
Assert.NotNull(output.Content);
Assert.True(output.ContentSet);
Assert.True(output.IsContentModified);
Assert.Empty(logger.Logged);
}
@ -223,7 +222,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.NotNull(output.TagName);
Assert.False(output.ContentSet);
Assert.False(output.IsContentModified);
}
[Theory]
@ -251,7 +250,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("script", output.TagName);
Assert.False(output.ContentSet);
Assert.False(output.IsContentModified);
Assert.Equal(2, logger.Logged.Count);
@ -286,7 +285,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("script", output.TagName);
Assert.False(output.ContentSet);
Assert.False(output.IsContentModified);
}
[Fact]
@ -309,7 +308,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("script", output.TagName);
Assert.False(output.ContentSet);
Assert.False(output.IsContentModified);
Assert.Single(logger.Logged);
@ -360,7 +359,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await helper.ProcessAsync(tagHelperContext, output);
// Assert
Assert.StartsWith("<script data-extra=\"something\" src=\"/blank.js\" data-more=\"else\"", output.Content);
Assert.StartsWith(
"<script data-extra=\"something\" src=\"/blank.js\" data-more=\"else\"", output.Content.GetContent());
Assert.Empty(logger.Logged);
}
@ -398,7 +398,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
await helper.ProcessAsync(context, output);
// Assert
Assert.Equal("<script src=\"/js/site.js\"></script><script src=\"/common.js\"></script>", output.Content);
Assert.Equal("<script src=\"/js/site.js\"></script><script src=\"/common.js\"></script>", output.Content.GetContent());
}
[Fact]
@ -436,7 +436,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("<script src=\"HtmlEncode[[/js/site.js]]\"></script>" +
"<script src=\"HtmlEncode[[/common.js]]\"></script>", output.Content);
"<script src=\"HtmlEncode[[/common.js]]\"></script>", output.Content.GetContent());
}
private TagHelperContext MakeTagHelperContext(
@ -449,7 +449,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes,
items: new Dictionary<object, object>(),
uniqueId: Guid.NewGuid().ToString("N"),
getChildContentAsync: () => Task.FromResult(content));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(content);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
}
private static ViewContext MakeViewContext()

View File

@ -202,14 +202,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = originalPostContent,
SelfClosing = true,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(originalPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
{
@ -232,9 +237,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.True(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
Assert.NotNull(viewContext.FormContext?.FormData);
@ -287,14 +292,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = originalPostContent,
SelfClosing = true,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(originalPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
{
@ -325,9 +335,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.True(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
Assert.NotNull(viewContext.FormContext?.FormData);
@ -386,14 +396,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = originalPostContent,
SelfClosing = true,
SelfClosing = true
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(originalPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
{
@ -425,9 +440,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.True(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
Assert.NotNull(viewContext.FormContext?.FormData);
@ -470,9 +485,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder());
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder());
var metadataProvider = new EmptyModelMetadataProvider();
string model = null;
var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), model);
@ -536,9 +556,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(tagName, originalAttributes, new HtmlEncoder());
var metadataProvider = new EmptyModelMetadataProvider();
var modelExplorer = metadataProvider.GetModelExplorerForType(modelType, model);
var modelExpression = new ModelExpression(propertyName, modelExplorer);
@ -592,7 +616,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder());
var tagHelper = new SelectTagHelper
{

View File

@ -30,7 +30,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.Append("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var expectedAttribute = new KeyValuePair<string, string>(attributeName, attributeValue);
// Act
@ -61,7 +66,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.Append("Something Else");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
// Act
tagHelperOutput.CopyHtmlAttribute(attributeName, tagHelperContext);

View File

@ -117,16 +117,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var htmlAttributes = new Dictionary<string, string>
{
{ "class", "form-control" },
};
var output = new TagHelperOutput(expectedTagName, htmlAttributes, new HtmlEncoder())
{
Content = "original content",
SelfClosing = true,
};
output.Content.SetContent("original content");
var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
{
@ -145,7 +150,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.True(output.SelfClosing);
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -174,14 +179,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(expectedTagName, expectedAttributes, new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
SelfClosing = true,
};
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
{
@ -200,7 +210,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.True(output.SelfClosing);
Assert.Equal(expectedTagName, output.TagName);
}

View File

@ -41,19 +41,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, string>
{
{ "id", "myvalidationmessage" }
},
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
var viewContext = TestableHtmlGenerator.GetViewContext(model: null,
htmlGenerator: htmlGenerator,
@ -74,9 +77,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("Name", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-replace"));
Assert.Equal("true", attribute.Value);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -95,16 +98,20 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
"span",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var expectedViewContext = CreateViewContext();
var generator = new Mock<IHtmlGenerator>();
generator
@ -121,9 +128,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator.Verify();
Assert.Equal("span", output.TagName);
Assert.Empty(output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
}
[Theory]
@ -141,16 +148,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var output = new TagHelperOutput(
"span",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
Content = outputContent
};
htmlEncoder: new HtmlEncoder());
output.Content.SetContent(outputContent);
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult(childContent));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(childContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{
InnerHtml = "New HTML"
@ -181,7 +191,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("bar", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-hello"));
Assert.Equal("world", attribute.Value);
Assert.Equal(expectedOutputContent, output.Content);
Assert.Equal(expectedOutputContent, output.Content.GetContent());
}
[Theory]
@ -204,7 +214,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult(childContent));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(childContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{
InnerHtml = "New HTML"
@ -235,7 +250,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("bar", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-hello"));
Assert.Equal("world", attribute.Value);
Assert.Equal(expectedOutputContent, output.Content);
Assert.Equal(expectedOutputContent, output.Content.GetContent());
}
[Fact]
@ -249,12 +264,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var output = new TagHelperOutput(
"span",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var viewContext = CreateViewContext();
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
validationMessageTagHelper.ViewContext = viewContext;
@ -266,9 +280,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("span", output.TagName);
Assert.Empty(output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
}
private static ModelExpression CreateModelExpression(string name)

View File

@ -47,19 +47,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something"));
getChildContentAsync: () =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, string>
{
{ "class", "form-control" }
},
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = "Custom Content",
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent("Custom Content");
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
Model model = null;
@ -76,10 +79,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("form-control validation-summary-valid", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-summary"));
Assert.Equal("true", attribute.Value);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal("Custom Content<ul><li style=\"display:none\"></li>" + Environment.NewLine + "</ul>",
output.PostContent);
output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
@ -101,12 +104,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var expectedViewContext = CreateViewContext();
var generator = new Mock<IHtmlGenerator>();
generator
@ -127,9 +129,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator.Verify();
Assert.Equal("div", output.TagName);
Assert.Empty(output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
}
[Fact]
@ -145,12 +147,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = "Content of validation summary"
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent("Content of validation summary");
var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{
InnerHtml = "New HTML"
@ -185,9 +186,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("world", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("anything"));
Assert.Equal("something", attribute.Value);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal("Content of validation summaryNew HTML", output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal("Content of validation summaryNew HTML", output.PostContent.GetContent());
}
[Fact]
@ -204,12 +205,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = expectedPostContent,
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var viewContext = CreateViewContext();
@ -222,9 +221,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("div", output.TagName);
Assert.Empty(output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal(expectedPostContent, output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
}
[Theory]
@ -242,12 +241,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{
PreContent = expectedPreContent,
Content = expectedContent,
PostContent = "Content of validation message",
};
htmlEncoder: new HtmlEncoder());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent("Content of validation message");
var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{
InnerHtml = "New HTML"
@ -273,9 +270,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("div", output.TagName);
Assert.Empty(output.Attributes);
Assert.Equal(expectedPreContent, output.PreContent);
Assert.Equal(expectedContent, output.Content);
Assert.Equal("Content of validation messageNew HTML", output.PostContent);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.Equal("Content of validation messageNew HTML", output.PostContent.GetContent());
generator.Verify();
}

View File

@ -18,7 +18,7 @@ namespace ActivatorWebSite.TagHelpers
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.PostContent = $"<footer>{HtmlHelper.Encode(ViewData["footer"])}</footer>";
output.PostContent.SetContent($"<footer>{HtmlHelper.Encode(ViewData["footer"])}</footer>");
}
}
}

View File

@ -20,7 +20,7 @@ namespace ActivatorWebSite.TagHelpers
{
var content = await context.GetChildContentAsync();
output.Content = HtmlHelper.Hidden(Name, content).ToString();
output.Content.SetContent(HtmlHelper.Hidden(Name, content).ToString());
}
}
}

View File

@ -25,12 +25,12 @@ namespace ActivatorWebSite.TagHelpers
if (string.IsNullOrEmpty(repeatContent))
{
repeatContent = content;
repeatContent = content.GetContent();
}
for (int i = 0; i < RepeatContent; i++)
{
output.Content += repeatContent;
output.Content.Append(repeatContent);
}
}

View File

@ -22,7 +22,7 @@ namespace ActivatorWebSite.TagHelpers
var builder = new TagBuilder("h2", HtmlHelper.HtmlEncoder);
var title = ViewContext.ViewBag.Title;
builder.InnerHtml = HtmlHelper.Encode(title);
output.PreContent = builder.ToString();
output.PreContent.SetContent(builder.ToString());
}
}
}

View File

@ -14,7 +14,7 @@ namespace RequestServicesWebSite
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Content = RequestIdService.RequestId;
output.Content.SetContent(RequestIdService.RequestId);
}
}
}

View File

@ -30,7 +30,7 @@ namespace TagHelpersWebSite.TagHelpers
output.Attributes["href"] = UrlHelper.Action(Action, Controller, methodParameters);
output.PreContent = "My ";
output.PreContent.SetContent("My ");
}
}
}

View File

@ -4,7 +4,6 @@
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Razor.TagHelpers;
namespace TagHelpersWebSite.TagHelpers
{
@ -16,10 +15,10 @@ namespace TagHelpersWebSite.TagHelpers
var childContent = await context.GetChildContentAsync();
// Find Urls in the content and replace them with their anchor tag equivalent.
output.Content = Regex.Replace(
childContent,
output.Content.SetContent(Regex.Replace(
childContent.GetContent(),
@"\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

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

View File

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

View File

@ -8,7 +8,6 @@ using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Razor.TagHelpers;
namespace MvcSample.Web.Components
{
@ -42,7 +41,7 @@ namespace MvcSample.Web.Components
writer));
output.TagName = null;
output.Content = writer.ToString();
output.Content.SetContent(writer.ToString());
}
public async Task<IViewComponentResult> InvokeAsync(int count)

View File

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