- Updated all tests and TagHelpers to utilize the new TagHelperOutput.Attributes and TagHelperContext.AllAttribute types.

aspnet/Razor#279
This commit is contained in:
N. Taylor Mullen 2015-04-23 16:02:07 -07:00
parent 05ac641f9a
commit f152ea7004
28 changed files with 956 additions and 388 deletions

View File

@ -288,7 +288,7 @@ namespace Microsoft.AspNet.Mvc.Razor
foreach (var attribute in tagHelperOutput.Attributes)
{
writer.Write(' ');
writer.Write(attribute.Key);
writer.Write(attribute.Name);
writer.Write("=\"");
WriteTo(writer, HtmlEncoder, attribute.Value, escapeQuotes: true);
writer.Write('"');

View File

@ -82,7 +82,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var routePrefixedAttributes = output.FindPrefixedAttributes(RouteAttributePrefix);
// If "href" is already set, it means the user is attempting to use a normal anchor.
if (output.Attributes.ContainsKey(Href))
if (output.Attributes.ContainsName(Href))
{
if (Action != null ||
Controller != null ||
@ -154,7 +154,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
private static Dictionary<string, object> GetRouteValues(
TagHelperOutput output,
IEnumerable<KeyValuePair<string, object>> routePrefixedAttributes)
IEnumerable<TagHelperAttribute> routePrefixedAttributes)
{
Dictionary<string, object> routeValues = null;
if (routePrefixedAttributes.Any())
@ -165,7 +165,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Remove prefix from keys and convert all values to strings. HtmlString and similar classes are not
// meaningful to routing.
routeValues = routePrefixedAttributes.ToDictionary(
attribute => attribute.Key.Substring(RouteAttributePrefix.Length),
attribute => attribute.Name.Substring(RouteAttributePrefix.Length),
attribute => (object)attribute.Value.ToString());
}

View File

@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var routePrefixedAttributes = output.FindPrefixedAttributes(RouteAttributePrefix);
// If "action" is already set, it means the user is attempting to use a normal <form>.
if (output.Attributes.ContainsKey(HtmlActionAttributeName))
if (output.Attributes.ContainsName(HtmlActionAttributeName))
{
if (Action != null || Controller != null || Route != null || routePrefixedAttributes.Any())
{
@ -146,7 +146,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
private static Dictionary<string, object> GetRouteValues(
TagHelperOutput output,
IEnumerable<KeyValuePair<string, object>> routePrefixedAttributes)
IEnumerable<TagHelperAttribute> routePrefixedAttributes)
{
Dictionary<string, object> routeValues = null;
if (routePrefixedAttributes.Any())
@ -157,7 +157,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Remove prefix from keys and convert all values to strings. HtmlString and similar classes are not
// meaningful to routing.
routeValues = routePrefixedAttributes.ToDictionary(
attribute => attribute.Key.Substring(RouteAttributePrefix.Length),
attribute => attribute.Name.Substring(RouteAttributePrefix.Length),
attribute => (object)attribute.Value.ToString());
}

View File

@ -155,7 +155,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
// inputType may be more specific than default the generator chooses below.
if (!output.Attributes.ContainsKey("type"))
if (!output.Attributes.ContainsName("type"))
{
output.Attributes["type"] = inputType;
}
@ -218,9 +218,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
// Prepare to move attributes from current element to <input type="checkbox"/> generated just below.
var htmlAttributes = output.Attributes.ToDictionary(
attribute => attribute.Key,
attribute => (object)attribute.Value);
var htmlAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
// Construct attributes correctly (first attribute wins).
foreach (var attribute in output.Attributes)
{
if (!htmlAttributes.ContainsKey(attribute.Name))
{
htmlAttributes.Add(attribute.Name, attribute.Value);
}
}
var tagBuilder = Generator.GenerateCheckBox(
ViewContext,

View File

@ -86,10 +86,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
foreach (var attribute in requiredAttributes)
{
if (!context.AllAttributes.ContainsKey(attribute) ||
if (!context.AllAttributes.ContainsName(attribute) ||
context.AllAttributes[attribute] == null ||
(typeof(string).IsAssignableFrom(context.AllAttributes[attribute].GetType()) &&
string.IsNullOrWhiteSpace(context.AllAttributes[attribute] as string)))
(typeof(string).IsAssignableFrom(context.AllAttributes[attribute].Value.GetType()) &&
string.IsNullOrWhiteSpace(context.AllAttributes[attribute].Value as string)))
{
// Missing attribute!
missingAttributes.Add(attribute);

View File

@ -236,7 +236,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var mode = modeResult.FullMatches.Select(match => match.Mode).Max();
// NOTE: Values in TagHelperOutput.Attributes may already be HTML-encoded.
var attributes = new Dictionary<string, object>(output.Attributes);
var attributes = new TagHelperAttributeList(output.Attributes);
var builder = new DefaultTagHelperContent();
@ -261,7 +261,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
output.Content.SetContent(builder);
}
private void BuildGlobbedLinkTags(IDictionary<string, object> attributes, TagHelperContent builder)
private void BuildGlobbedLinkTags(TagHelperAttributeList attributes, TagHelperContent builder)
{
EnsureGlobbingUrlBuilder();
@ -341,7 +341,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
}
private void BuildLinkTag(IDictionary<string, object> attributes, TagHelperContent builder)
private void BuildLinkTag(TagHelperAttributeList attributes, TagHelperContent builder)
{
EnsureFileVersionProvider();
builder.Append("<link ");
@ -350,7 +350,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
var attributeValue = attribute.Value;
if (FileVersion == true &&
string.Equals(attribute.Key, HrefAttributeName, StringComparison.OrdinalIgnoreCase))
string.Equals(attribute.Name, HrefAttributeName, StringComparison.OrdinalIgnoreCase))
{
// "href" values come from bound attributes and globbing. So anything but a non-null string is
// unexpected but could happen if another helper targeting the same element does something odd.
@ -363,7 +363,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
builder
.Append(attribute.Key)
.Append(attribute.Name)
.Append("=\"")
.Append(HtmlEncoder, ViewContext.Writer.Encoding, attributeValue)
.Append("\" ");

View File

@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
// Nothing to do if this <option/> is already selected.
if (!output.Attributes.ContainsKey("selected"))
if (!output.Attributes.ContainsName("selected"))
{
// Is this <option/> element a child of a <select/> element the SelectTagHelper targeted?
object formDataEntry;

View File

@ -205,7 +205,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var mode = modeResult.FullMatches.Select(match => match.Mode).Max();
// NOTE: Values in TagHelperOutput.Attributes may already be HTML-encoded.
var attributes = new Dictionary<string, object>(output.Attributes);
var attributes = new TagHelperAttributeList(output.Attributes);
var builder = new DefaultTagHelperContent();
var originalContent = await context.GetChildContentAsync();
@ -233,7 +233,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
private void BuildGlobbedScriptTags(
TagHelperContent originalContent,
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
TagHelperContent builder)
{
EnsureGlobbingUrlBuilder();
@ -257,7 +257,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
}
private void BuildFallbackBlock(IDictionary<string, object> attributes, DefaultTagHelperContent builder)
private void BuildFallbackBlock(TagHelperAttributeList attributes, DefaultTagHelperContent builder)
{
EnsureGlobbingUrlBuilder();
EnsureFileVersionProvider();
@ -272,10 +272,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Append("||document.write(\"");
// May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound.
if (!attributes.ContainsKey(SrcAttributeName))
if (!attributes.ContainsName(SrcAttributeName))
{
// Need this entry to place each fallback source.
attributes.Add(SrcAttributeName, null);
attributes.Add(new TagHelperAttribute(SrcAttributeName, value: null));
}
foreach (var src in fallbackSrcs)
@ -287,9 +287,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
foreach (var attribute in attributes)
{
if (!attribute.Key.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
{
var encodedKey = JavaScriptEncoder.JavaScriptStringEncode(attribute.Key);
var encodedKey = JavaScriptEncoder.JavaScriptStringEncode(attribute.Name);
var attributeValue = attribute.Value.ToString();
var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);
@ -307,7 +307,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// attribute.Key ("src") does not need to be JavaScript-encoded.
var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);
AppendAttribute(builder, attribute.Key, encodedValue, escapeQuotes: true);
AppendAttribute(builder, attribute.Name, encodedValue, escapeQuotes: true);
}
}
@ -342,7 +342,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
private void BuildScriptTag(
TagHelperContent content,
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
TagHelperContent builder)
{
EnsureFileVersionProvider();
@ -352,7 +352,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
var attributeValue = attribute.Value;
if (FileVersion == true &&
string.Equals(attribute.Key, SrcAttributeName, StringComparison.OrdinalIgnoreCase))
string.Equals(attribute.Name, SrcAttributeName, StringComparison.OrdinalIgnoreCase))
{
// "src" values come from bound attributes and globbing. So anything but a non-null string is
// unexpected but could happen if another helper targeting the same element does something odd.
@ -364,7 +364,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
}
AppendAttribute(builder, attribute.Key, attributeValue, escapeQuotes: false);
AppendAttribute(builder, attribute.Name, attributeValue, escapeQuotes: false);
}
builder.Append(">")

View File

@ -31,21 +31,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[NotNull] string attributeName,
[NotNull] TagHelperContext context)
{
if (!tagHelperOutput.Attributes.ContainsKey(attributeName))
if (!tagHelperOutput.Attributes.ContainsName(attributeName))
{
IEnumerable<IReadOnlyTagHelperAttribute> entries;
// We look for the original attribute so we can restore the exact attribute name the user typed.
// Approach also ignores changes made to tagHelperOutput[attributeName].
var entry = context.AllAttributes.FirstOrDefault(
attribute => attribute.Key.Equals(attributeName, StringComparison.OrdinalIgnoreCase));
if (entry.Equals(default(KeyValuePair<string, object>)))
if (!context.AllAttributes.TryGetAttributes(attributeName, out entries))
{
throw new ArgumentException(
Resources.FormatTagHelperOutput_AttributeDoesNotExist(attributeName, nameof(TagHelperContext)),
nameof(attributeName));
}
tagHelperOutput.Attributes.Add(entry.Key, entry.Value);
foreach (var entry in entries)
{
tagHelperOutput.Attributes.Add(entry.Name, entry.Value);
}
}
}
@ -57,7 +59,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
/// <param name="prefix">A prefix to look for.</param>
/// <returns><see cref="KeyValuePair{string, string}"/>s with <see cref="KeyValuePair{string, string}.Key"/>
/// starting with the given <paramref name="prefix"/>.</returns>
public static IEnumerable<KeyValuePair<string, object>> FindPrefixedAttributes(
public static IEnumerable<TagHelperAttribute> FindPrefixedAttributes(
[NotNull] this TagHelperOutput tagHelperOutput,
[NotNull] string prefix)
{
@ -65,7 +67,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// We're only interested in HTML attributes that have the desired prefix.
var prefixedAttributes = tagHelperOutput.Attributes
.Where(attribute => attribute.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
.Where(attribute => attribute.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
.ToArray();
return prefixedAttributes;
@ -85,13 +87,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
foreach (var attribute in tagBuilder.Attributes)
{
if (!tagHelperOutput.Attributes.ContainsKey(attribute.Key))
if (!tagHelperOutput.Attributes.ContainsName(attribute.Key))
{
tagHelperOutput.Attributes.Add(attribute.Key, attribute.Value);
}
else if (attribute.Key.Equals("class", StringComparison.OrdinalIgnoreCase))
{
tagHelperOutput.Attributes["class"] += " " + attribute.Value;
TagHelperAttribute classAttribute;
if (tagHelperOutput.Attributes.TryGetAttribute("class", out classAttribute))
{
tagHelperOutput.Attributes["class"] = classAttribute.Value + " " + attribute.Value;
}
else
{
tagHelperOutput.Attributes.Add("class", attribute.Value);
}
}
}
}
@ -104,7 +115,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
/// <param name="attributes">Attributes to remove.</param>
public static void RemoveRange(
[NotNull] this TagHelperOutput tagHelperOutput,
[NotNull] IEnumerable<KeyValuePair<string, object>> attributes)
[NotNull] IEnumerable<TagHelperAttribute> attributes)
{
foreach (var attribute in attributes)
{

View File

@ -7,7 +7,7 @@
<title></title>
</head>
<body>
<form action="HtmlEncode[[/MvcTagHelper_Home/ProductSubmit]]" method="get">
<form method="get" action="HtmlEncode[[/MvcTagHelper_Home/ProductSubmit]]">
<div>
<label class="product" for="HtmlEncode[[HomePage]]">HtmlEncode[[HomePage]]</label>
<input size="50" type="HtmlEncode[[url]]" id="HtmlEncode[[HomePage]]" name="HtmlEncode[[HomePage]]" value="HtmlEncode[[http://www.contoso.com/]]" />

View File

@ -7,7 +7,7 @@
<title></title>
</head>
<body>
<form action="/MvcTagHelper_Home/ProductSubmit" method="get">
<form method="get" action="/MvcTagHelper_Home/ProductSubmit">
<div>
<label class="product" for="HomePage">HomePage</label>
<input size="50" type="url" id="HomePage" name="HomePage" value="http://www.contoso.com/" />

View File

@ -747,7 +747,7 @@ namespace Microsoft.AspNet.Mvc.Razor
// parameters: TagName, Attributes, SelfClosing, PreContent, Content, PostContent
GetTagHelperOutput(
tagName: "div",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: null,
@ -759,7 +759,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: null,
@ -771,7 +771,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: " ",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: null,
@ -783,7 +783,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" } },
attributes: new TagHelperAttributeList() { { "test", "testVal" } },
selfClosing: false,
preElement: null,
preContent: null,
@ -795,7 +795,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
attributes: new TagHelperAttributeList() { { "test", "testVal" }, { "something", " spaced " } },
selfClosing: false,
preElement: null,
preContent: null,
@ -807,7 +807,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" } },
attributes: new TagHelperAttributeList() { { "test", "testVal" } },
selfClosing: true,
preElement: null,
preContent: null,
@ -819,7 +819,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
attributes: new TagHelperAttributeList() { { "test", "testVal" }, { "something", " spaced " } },
selfClosing: true,
preElement: null,
preContent: null,
@ -831,7 +831,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: "Hello World!",
@ -843,7 +843,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: null,
@ -855,7 +855,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: null,
@ -867,7 +867,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: "Hello",
@ -879,7 +879,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: true,
preElement: null,
preContent: "Hello",
@ -891,7 +891,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: "Hello",
@ -903,7 +903,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "random",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: true,
preElement: null,
preContent: "Hello",
@ -915,7 +915,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: "Before",
preContent: null,
@ -927,7 +927,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: "Before",
preContent: null,
@ -939,7 +939,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object> { { "test", "testVal" } },
attributes: new TagHelperAttributeList { { "test", "testVal" } },
selfClosing: true,
preElement: "Before",
preContent: null,
@ -951,7 +951,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object> { { "test", "testVal" } },
attributes: new TagHelperAttributeList { { "test", "testVal" } },
selfClosing: true,
preElement: "Before",
preContent: null,
@ -963,7 +963,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: true,
preElement: "Before",
preContent: null,
@ -975,7 +975,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: null,
@ -987,7 +987,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: null,
preContent: null,
@ -999,7 +999,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object> { { "test", "testVal" } },
attributes: new TagHelperAttributeList { { "test", "testVal" } },
selfClosing: true,
preElement: null,
preContent: null,
@ -1011,7 +1011,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object> { { "test", "testVal" } },
attributes: new TagHelperAttributeList { { "test", "testVal" } },
selfClosing: true,
preElement: null,
preContent: null,
@ -1023,7 +1023,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: true,
preElement: null,
preContent: null,
@ -1035,7 +1035,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: "Before",
preContent: "Hello",
@ -1047,7 +1047,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object> { { "test", "testVal" } },
attributes: new TagHelperAttributeList { { "test", "testVal" } },
selfClosing: false,
preElement: "Before",
preContent: "Hello",
@ -1059,7 +1059,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: true,
preElement: "Before",
preContent: "Hello",
@ -1071,7 +1071,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: true,
preElement: "Before",
preContent: "Hello",
@ -1083,7 +1083,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
attributes: new TagHelperAttributeList(),
selfClosing: false,
preElement: "Before",
preContent: "Hello",
@ -1095,7 +1095,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object> { { "test", "testVal" } },
attributes: new TagHelperAttributeList { { "test", "testVal" } },
selfClosing: false,
preElement: "Before",
preContent: "Hello",
@ -1161,7 +1161,7 @@ namespace Microsoft.AspNet.Mvc.Razor
},
startTagHelperWritingScope: () => { },
endTagHelperWritingScope: () => defaultTagHelperContent);
tagHelperExecutionContext.Output = new TagHelperOutput("p", new Dictionary<string, object>());
tagHelperExecutionContext.Output = new TagHelperOutput("p", new TagHelperAttributeList());
if (childContentRetrieved)
{
await tagHelperExecutionContext.GetChildContentAsync();
@ -1193,7 +1193,7 @@ namespace Microsoft.AspNet.Mvc.Razor
executeChildContentAsync: () => { return Task.FromResult(result: true); },
startTagHelperWritingScope: () => { },
endTagHelperWritingScope: () => new DefaultTagHelperContent());
tagHelperExecutionContext.Output = new TagHelperOutput("p", new Dictionary<string, object>());
tagHelperExecutionContext.Output = new TagHelperOutput("p", new TagHelperAttributeList());
tagHelperExecutionContext.Output.Content.SetContent("Hello World!");
// Act
@ -1238,7 +1238,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private static TagHelperOutput GetTagHelperOutput(
string tagName,
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
bool selfClosing,
string preElement,
string preContent,

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
@ -24,7 +25,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var metadataProvider = new TestModelMetadataProvider();
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>
allAttributes: new TagHelperAttributeList
{
{ "id", "myanchor" },
{ "asp-route-foo", "bar" },
@ -44,7 +45,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
{ "id", "myanchor" },
{ "asp-route-foo", "bar" },
@ -74,9 +75,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(2, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("id"));
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("id"));
Assert.Equal("myanchor", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("href"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("href"));
Assert.Equal("home/index", attribute.Value);
Assert.Equal("Something", output.Content.GetContent());
Assert.Equal(expectedTagName, output.TagName);
@ -87,7 +88,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -98,7 +100,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
"a",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.Content.SetContent(string.Empty);
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
@ -129,7 +131,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -140,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
"a",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.Content.SetContent(string.Empty);
var generator = new Mock<IHtmlGenerator>();
@ -181,7 +184,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var anchorTagHelper = new AnchorTagHelper();
var output = new TagHelperOutput(
"a",
attributes: new Dictionary<string, object>()
attributes: new TagHelperAttributeList
{
{ "href", "http://www.contoso.com" }
});
@ -219,7 +222,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
typeof(AnchorTagHelper).GetProperty(propertyName).SetValue(anchorTagHelper, "Home");
var output = new TagHelperOutput(
"a",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var expectedErrorMessage = "Cannot determine an 'href' attribute for <a>. An <a> with a specified " +
"'asp-route' must not have an 'asp-action' or 'asp-controller' attribute.";

View File

@ -255,7 +255,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
cache.Setup(c => c.TryGetValue(It.IsAny<string>(), It.IsAny<IEntryLink>(), out cacheResult))
.Returns(false);
var tagHelperContext = GetTagHelperContext(id, childContent);
var tagHelperOutput = new TagHelperOutput("cache", new Dictionary<string, object>());
var tagHelperOutput = new TagHelperOutput("cache", new TagHelperAttributeList());
var cacheTagHelper = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -295,7 +295,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
cache.Setup(c => c.TryGetValue(It.IsAny<string>(), It.IsAny<IEntryLink>(), out cacheResult))
.Returns(false);
var tagHelperContext = GetTagHelperContext(id, childContent);
var tagHelperOutput = new TagHelperOutput("cache", new Dictionary<string, object>());
var tagHelperOutput = new TagHelperOutput("cache", new TagHelperAttributeList());
var cacheTagHelper = new CacheTagHelper
{
ViewContext = GetViewContext(),
@ -327,7 +327,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var childContent = "original-child-content";
var cache = new MemoryCache(new MemoryCacheOptions());
var tagHelperContext1 = GetTagHelperContext(id, childContent);
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, object>());
var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList());
var cacheTagHelper1 = new CacheTagHelper
{
VaryByQuery = "key1,key2",
@ -348,7 +348,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange - 2
var tagHelperContext2 = GetTagHelperContext(id, "different-content");
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, object>());
var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList());
var cacheTagHelper2 = new CacheTagHelper
{
VaryByQuery = "key1,key2",
@ -376,8 +376,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var childContent1 = "original-child-content";
var cache = new MemoryCache(new MemoryCacheOptions());
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput1.PreContent.Append("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
@ -400,9 +399,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange - 2
var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput(
"cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
@ -611,8 +608,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Returns(() => currentTime);
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput1.PreContent.SetContent("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
@ -634,8 +630,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange - 2
var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
@ -668,8 +663,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Returns(() => currentTime);
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput1.PreContent.SetContent("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
@ -692,8 +686,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
currentTime = currentTime.AddMinutes(5).AddSeconds(2);
var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
@ -725,8 +718,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Returns(() => currentTime);
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput1.PreContent.SetContent("<cache>");
tagHelperOutput1.PostContent.SetContent("</cache>");
var cacheTagHelper1 = new CacheTagHelper
@ -749,8 +741,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
currentTime = currentTime.AddSeconds(35);
var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput2.PreContent.SetContent("<cache>");
tagHelperOutput2.PostContent.SetContent("</cache>");
var cacheTagHelper2 = new CacheTagHelper
@ -780,7 +771,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var tokenSource = new CancellationTokenSource();
var cache = new MemoryCache(new MemoryCacheOptions());
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new TagHelperAttributeList(),
items: new Dictionary<object, object>(),
uniqueId: id,
getChildContentAsync: () =>
@ -793,8 +784,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
return Task.FromResult<TagHelperContent>(expectedContent);
});
var tagHelperOutput = new TagHelperOutput("cache",
new Dictionary<string, object> { { "attr", "value" } });
var tagHelperOutput = new TagHelperOutput("cache", new TagHelperAttributeList { { "attr", "value" } });
tagHelperOutput.PreContent.SetContent("<cache>");
tagHelperOutput.PostContent.SetContent("</cache>");
var cacheTagHelper = new CacheTagHelper
@ -837,7 +827,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string childContent = "some child content")
{
return new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new TagHelperAttributeList(),
items: new Dictionary<object, object>(),
uniqueId: id,
getChildContentAsync: () =>

View File

@ -80,7 +80,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
// Arrange
var content = "content";
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object> { { "names", namesAttribute } },
attributes: new TagHelperAttributeList { { "names", namesAttribute } },
content: content);
var output = MakeTagHelperOutput("environment");
var hostingEnvironment = new Mock<IHostingEnvironment>();
@ -108,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
// Arrange
var content = "content";
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object> { { "names", namesAttribute } },
attributes: new TagHelperAttributeList { { "names", namesAttribute } },
content: content);
var output = MakeTagHelperOutput("environment");
var hostingEnvironment = new Mock<IHostingEnvironment>();
@ -129,10 +129,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
}
private TagHelperContext MakeTagHelperContext(
IDictionary<string, object> attributes = null,
TagHelperAttributeList attributes = null,
string content = null)
{
attributes = attributes ?? new Dictionary<string, object>();
attributes = attributes ?? new TagHelperAttributeList();
return new TagHelperContext(
attributes,
@ -146,9 +146,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
});
}
private TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, object> attributes = null)
private TagHelperOutput MakeTagHelperOutput(string tagName, TagHelperAttributeList attributes = null)
{
attributes = attributes ?? new Dictionary<string, object>();
attributes = attributes ?? new TagHelperAttributeList();
return new TagHelperOutput(tagName, attributes);
}

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
@ -25,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedTagName = "not-form";
var metadataProvider = new TestModelMetadataProvider();
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>
allAttributes: new TagHelperAttributeList
{
{ "id", "myform" },
{ "asp-route-foo", "bar" },
@ -44,7 +45,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
{ "id", "myform" },
{ "asp-route-foo", "bar" },
@ -74,11 +75,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(3, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("id"));
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("id"));
Assert.Equal("myform", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("method"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("method"));
Assert.Equal("post", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("action"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("action"));
Assert.Equal("home/index", attribute.Value);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
@ -97,7 +98,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var viewContext = CreateViewContext();
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -108,7 +110,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
"form",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
generator
.Setup(mock => mock.GenerateForm(
@ -148,7 +150,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var testViewContext = CreateViewContext();
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -157,10 +160,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var expectedAttribute = new KeyValuePair<string, object>("asp-ROUTEE-NotRoute", "something");
var expectedAttribute = new TagHelperAttribute("asp-ROUTEE-NotRoute", "something");
var output = new TagHelperOutput(
"form",
attributes: new Dictionary<string, object>()
attributes: new TagHelperAttributeList()
{
{ "asp-route-val", "hello" },
{ "asp-roUte--Foo", "bar" }
@ -185,9 +188,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var routeValueDictionary = (Dictionary<string, object>)routeValues;
Assert.Equal(2, routeValueDictionary.Count);
var routeValue = Assert.Single(routeValueDictionary, kvp => kvp.Key.Equals("val"));
var routeValue = Assert.Single(routeValueDictionary, attr => attr.Key.Equals("val"));
Assert.Equal("hello", routeValue.Value);
routeValue = Assert.Single(routeValueDictionary, kvp => kvp.Key.Equals("-Foo"));
routeValue = Assert.Single(routeValueDictionary, attr => attr.Key.Equals("-Foo"));
Assert.Equal("bar", routeValue.Value);
})
.Returns(new TagBuilder("form", new CommonTestEncoder()))
@ -219,7 +222,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var viewContext = CreateViewContext();
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -230,7 +234,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
"form",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
generator
.Setup(mock => mock.GenerateForm(viewContext, "Index", "Home", null, null, null))
@ -264,7 +268,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var viewContext = CreateViewContext();
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -275,7 +280,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
"form",
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
{ "asp-route-foo", "bar" }
});
@ -333,12 +338,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
};
var output = new TagHelperOutput("form",
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
{ "aCTiON", "my-action" },
});
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -356,7 +362,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("form", output.TagName);
Assert.False(output.SelfClosing);
var attribute = Assert.Single(output.Attributes);
Assert.Equal(new KeyValuePair<string, object>("aCTiON", "my-action"), attribute);
Assert.Equal(new TagHelperAttribute("aCTiON", "my-action"), attribute);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.IsEmpty);
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
@ -372,7 +378,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var formTagHelper = new FormTagHelper();
var tagHelperOutput = new TagHelperOutput(
"form",
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
{ "action", "my-action" },
});
@ -409,7 +415,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
typeof(FormTagHelper).GetProperty(propertyName).SetValue(formTagHelper, "Home");
var output = new TagHelperOutput(
"form",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var expectedErrorMessage = "Cannot determine an 'action' attribute for <form>. A <form> with a specified " +
"'asp-route' must not have an 'asp-action' or 'asp-controller' attribute.";

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
@ -18,6 +19,96 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
public class InputTagHelperTest
{
public static TheoryData MultiAttributeCheckBoxData
{
get
{
// outputAttributes, expectedAttributeString
return new TheoryData<TagHelperAttributeList, string>
{
{
new TagHelperAttributeList
{
{ "hello", "world" },
{ "hello", "world2" }
},
"hello=\"HtmlEncode[[world]]\""
},
{
new TagHelperAttributeList
{
{ "hello", "world" },
{ "hello", "world2" },
{ "hello", "world3" }
},
"hello=\"HtmlEncode[[world]]\""
},
{
new TagHelperAttributeList
{
{ "HelLO", "world" },
{ "HELLO", "world2" }
},
"HelLO=\"HtmlEncode[[world]]\""
},
{
new TagHelperAttributeList
{
{ "Hello", "world" },
{ "HELLO", "world2" },
{ "hello", "world3" }
},
"Hello=\"HtmlEncode[[world]]\""
},
{
new TagHelperAttributeList
{
{ "HeLlO", "world" },
{ "hello", "world2" }
},
"HeLlO=\"HtmlEncode[[world]]\""
},
};
}
}
[Theory]
[MemberData(nameof(MultiAttributeCheckBoxData))]
public async Task CheckBoxHandlesMultipleAttributesSameNameCorrectly(
TagHelperAttributeList outputAttributes,
string expectedAttributeString)
{
// Arrange
var originalContent = "original content";
var originalTagName = "not-input";
var expectedContent = $"{originalContent}<input {expectedAttributeString} id=\"HtmlEncode[[IsACar]]\" " +
"name=\"HtmlEncode[[IsACar]]\" type=\"HtmlEncode[[checkbox]]\" value=\"HtmlEncode[[true]]\" />" +
"<input name=\"HtmlEncode[[IsACar]]\" type=\"HtmlEncode[[hidden]]\" value=\"HtmlEncode[[false]]\" />";
var context = new TagHelperContext(
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult<TagHelperContent>(result: null));
var output = new TagHelperOutput(originalTagName, outputAttributes)
{
SelfClosing = true,
};
output.Content.SetContent(originalContent);
var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider());
var tagHelper = GetTagHelper(htmlGenerator, model: false, propertyName: nameof(Model.IsACar));
// Act
await tagHelper.ProcessAsync(context, output);
// Assert
Assert.Empty(output.Attributes); // Moved to Content and cleared
Assert.Equal(expectedContent, output.Content.GetContent());
Assert.True(output.SelfClosing);
Assert.Null(output.TagName); // Cleared
}
// Top-level container (List<Model> or Model instance), immediate container type (Model or NestModel),
// model accessor, expression path / id, expected value.
public static TheoryData<object, Type, object, NameAndId, string> TestDataSet
@ -84,7 +175,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string expectedValue)
{
// Arrange
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
{ "type", "text" },
@ -99,7 +190,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedTagName = "not-input";
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -108,7 +200,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -160,7 +252,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content";
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -169,7 +262,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -236,7 +329,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string model)
{
// Arrange
var contextAttributes = new Dictionary<string, object>
var contextAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -245,7 +338,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
}
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "form-control hidden-control" },
{ "type", inputTypeName ?? "hidden" }, // Generator restores type attribute; adds "hidden" if none.
@ -265,7 +358,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -335,7 +428,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string model)
{
// Arrange
var contextAttributes = new Dictionary<string, object>
var contextAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -344,7 +437,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
}
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "form-control password-control" },
{ "type", inputTypeName ?? "password" }, // Generator restores type attribute; adds "password" if none.
@ -364,7 +457,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -429,7 +522,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var value = "match"; // Real generator would use this for comparison with For.Metadata.Model.
var contextAttributes = new Dictionary<string, object>
var contextAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
{ "value", value },
@ -439,7 +532,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
}
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "form-control radio-control" },
{ "type", inputTypeName ?? "radio" }, // Generator restores type attribute; adds "radio" if none.
@ -460,7 +553,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -536,7 +629,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string model)
{
// Arrange
var contextAttributes = new Dictionary<string, object>
var contextAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -545,7 +638,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
}
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "form-control text-control" },
{ "type", inputTypeName ?? "text" }, // Generator restores type attribute; adds "text" if none.
@ -565,7 +658,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
@ -668,19 +761,20 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string expectedType)
{
// Arrange
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "type", expectedType }, // Calculated; not passed to HtmlGenerator.
};
var expectedTagName = "not-input";
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
var output = new TagHelperOutput(expectedTagName, attributes: new Dictionary<string, object>())
var output = new TagHelperOutput(expectedTagName, attributes: new TagHelperAttributeList())
{
SelfClosing = true,
};
@ -748,19 +842,20 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string expectedType)
{
// Arrange
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "type", expectedType }, // Calculated; not passed to HtmlGenerator.
};
var expectedTagName = "not-input";
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
var output = new TagHelperOutput(expectedTagName, attributes: new Dictionary<string, object>())
var output = new TagHelperOutput(expectedTagName, attributes: new TagHelperAttributeList())
{
SelfClosing = true,
};

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Xunit;
@ -19,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
{
ModeAttributes.Create("mode0", new [] { "first-attr" })
};
var attributes = new Dictionary<string, object>
var attributes = new TagHelperAttributeList
{
["first-attr"] = "value",
["not-in-any-mode"] = "value"
@ -47,7 +48,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
{
ModeAttributes.Create("mode0", new [] { "first-attr", "second-attr" })
};
var attributes = new Dictionary<string, object>
var attributes = new TagHelperAttributeList
{
["first-attr"] = "value",
["second-attr"] = "value",
@ -82,7 +83,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
ModeAttributes.Create("mode2", new [] { "first-attr", "second-attr", "third-attr" }),
ModeAttributes.Create("mode3", new [] { "fourth-attr" })
};
var attributes = new Dictionary<string, object>
var attributes = new TagHelperAttributeList
{
["second-attr"] = "value",
["third-attr"] = "value",
@ -119,10 +120,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
}
private static TagHelperContext MakeTagHelperContext(
IDictionary<string, object> attributes = null,
TagHelperAttributeList attributes = null,
string content = null)
{
attributes = attributes ?? new Dictionary<string, object>();
attributes = attributes ?? new TagHelperAttributeList();
return new TagHelperContext(
attributes,

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
@ -164,7 +165,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var expectedTagName = "not-label";
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
{ "for", tagHelperOutputContent.ExpectedId }
@ -186,7 +187,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content";
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -195,7 +197,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent(tagHelperOutputContent.OriginalChildContent);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var htmlAttributes = new Dictionary<string, object>
var htmlAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};

View File

@ -28,14 +28,118 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
public class LinkTagHelperTest
{
public static TheoryData MultiAttributeSameNameData
{
get
{
// outputAttributes, expectedAttributeString
return new TheoryData<TagHelperAttributeList, string>
{
{
new TagHelperAttributeList
{
{ "hello", "world" },
{ "hello", "world2" }
},
"hello=\"HtmlEncode[[world]]\" hello=\"HtmlEncode[[world2]]\""
},
{
new TagHelperAttributeList
{
{ "hello", "world" },
{ "hello", "world2" },
{ "hello", "world3" }
},
"hello=\"HtmlEncode[[world]]\" hello=\"HtmlEncode[[world2]]\" hello=\"HtmlEncode[[world3]]\""
},
{
new TagHelperAttributeList
{
{ "HelLO", "world" },
{ "HELLO", "world2" }
},
"HelLO=\"HtmlEncode[[world]]\" HELLO=\"HtmlEncode[[world2]]\""
},
{
new TagHelperAttributeList
{
{ "Hello", "world" },
{ "HELLO", "world2" },
{ "hello", "world3" }
},
"Hello=\"HtmlEncode[[world]]\" HELLO=\"HtmlEncode[[world2]]\" hello=\"HtmlEncode[[world3]]\""
},
{
new TagHelperAttributeList
{
{ "HeLlO", "world" },
{ "hello", "world2" }
},
"HeLlO=\"HtmlEncode[[world]]\" hello=\"HtmlEncode[[world2]]\""
},
};
}
}
[Theory]
[MemberData(nameof(MultiAttributeSameNameData))]
public void HandlesMultipleAttributesSameNameCorrectly(
TagHelperAttributeList outputAttributes,
string expectedAttributeString)
{
// Arrange
var allAttributes = new TagHelperAttributeList(
outputAttributes.Concat(
new TagHelperAttributeList
{
{ "rel", new HtmlString("stylesheet") },
{ "href", "test.css" },
{ "asp-fallback-href", "test.css" },
{ "asp-fallback-test-class", "hidden" },
{ "asp-fallback-test-property", "visibility" },
{ "asp-fallback-test-value", "hidden" },
}));
var context = MakeTagHelperContext(allAttributes);
var combinedOutputAttributes = new TagHelperAttributeList(
outputAttributes.Concat(
new[]
{
new TagHelperAttribute("rel", new HtmlString("stylesheet"))
}));
var output = MakeTagHelperOutput("link", combinedOutputAttributes);
var logger = new Mock<ILogger<LinkTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
var viewContext = MakeViewContext();
var helper = new LinkTagHelper
{
HtmlEncoder = new CommonTestEncoder(),
JavaScriptEncoder = new CommonTestEncoder(),
Logger = logger.Object,
HostingEnvironment = hostingEnvironment,
ViewContext = viewContext,
FallbackHref = "test.css",
FallbackTestClass = "hidden",
FallbackTestProperty = "visibility",
FallbackTestValue = "hidden",
Href = "test.css",
Cache = MakeCache(),
};
// Act
helper.Process(context, output);
// Assert
Assert.StartsWith("<link " + expectedAttributeString + " rel=\"stylesheet\"", output.Content.GetContent());
}
public static TheoryData RunsWhenRequiredAttributesArePresent_Data
{
get
{
return new TheoryData<IDictionary<string, object>, Action<LinkTagHelper>>
return new TheoryData<TagHelperAttributeList, Action<LinkTagHelper>>
{
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-href-include"] = "*.css"
},
@ -45,7 +149,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-href-include"] = "*.css",
["asp-href-exclude"] = "*.min.css"
@ -57,7 +161,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-href"] = "test.css",
["asp-fallback-test-class"] = "hidden",
@ -73,7 +177,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-href-include"] = "*.css",
["asp-fallback-test-class"] = "hidden",
@ -90,7 +194,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
// File Version
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-file-version"] = "true"
},
@ -100,7 +204,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-href-include"] = "*.css",
["asp-file-version"] = "true"
@ -112,7 +216,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-href-include"] = "*.css",
["asp-href-exclude"] = "*.min.css",
@ -126,7 +230,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-href"] = "test.css",
["asp-fallback-test-class"] = "hidden",
@ -144,7 +248,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-href-include"] = "*.css",
["asp-fallback-test-class"] = "hidden",
@ -168,7 +272,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[Theory]
[MemberData(nameof(RunsWhenRequiredAttributesArePresent_Data))]
public void RunsWhenRequiredAttributesArePresent(
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
Action<LinkTagHelper> setProperties)
{
// Arrange
@ -202,21 +306,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
["data-extra"] = new HtmlString("something"),
["href"] = "test.css",
["asp-fallback-href"] = "test.css",
["asp-fallback-test-class"] = "hidden",
["asp-fallback-test-property"] = "visibility",
["asp-fallback-test-value"] = "hidden"
{ "rel", new HtmlString("stylesheet") },
{ "data-extra", new HtmlString("something") },
{ "href", "test.css" },
{ "asp-fallback-href", "test.css" },
{ "asp-fallback-test-class", "hidden" },
{ "asp-fallback-test-property", "visibility" },
{ "asp-fallback-test-value", "hidden" },
});
var output = MakeTagHelperOutput("link",
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
["data-extra"] = new HtmlString("something"),
{ "rel", new HtmlString("stylesheet") },
{ "data-extra", new HtmlString("something") },
});
var logger = new Mock<ILogger<LinkTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -248,10 +352,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
get
{
return new TheoryData<IDictionary<string, object>, Action<LinkTagHelper>>
return new TheoryData<TagHelperAttributeList, Action<LinkTagHelper>>
{
{
new Dictionary<string, object>
new TagHelperAttributeList
{
// This is commented out on purpose: ["asp-href-include"] = "*.css",
["asp-href-exclude"] = "*.min.css"
@ -263,7 +367,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
// This is commented out on purpose: ["asp-fallback-href"] = "test.css",
["asp-fallback-test-class"] = "hidden",
@ -279,7 +383,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-href"] = "test.css",
["asp-fallback-test-class"] = "hidden",
@ -295,7 +399,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
// This is commented out on purpose: ["asp-fallback-href-include"] = "test.css",
["asp-fallback-href-exclude"] = "**/*.min.css",
@ -319,7 +423,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[Theory]
[MemberData(nameof(DoesNotRunWhenARequiredAttributeIsMissing_Data))]
public void DoesNotRunWhenARequiredAttributeIsMissing(
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
Action<LinkTagHelper> setProperties)
{
// Arrange
@ -375,15 +479,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
["href"] = "/css/site.css",
["asp-href-include"] = "**/*.css"
{ "rel", new HtmlString("stylesheet") },
{ "href", "/css/site.css" },
{ "asp-href-include", "**/*.css" },
});
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
var output = MakeTagHelperOutput("link", attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
{ "rel", new HtmlString("stylesheet") },
});
var logger = new Mock<ILogger<LinkTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -418,13 +522,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["rel"] = "stylesheet",
["href"] = "/css/site.css",
["asp-href-include"] = "**/*.css"
});
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
var output = MakeTagHelperOutput("link", attributes: new TagHelperAttributeList
{
["rel"] = "stylesheet",
});
@ -461,15 +565,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
["href"] = "/css/site.css",
["asp-file-version"] = "true"
{ "rel", new HtmlString("stylesheet") },
{ "href", "/css/site.css" },
{ "asp-file-version", "true" }
});
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
var output = MakeTagHelperOutput("link", attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
{ "rel", new HtmlString("stylesheet") },
});
var logger = new Mock<ILogger<LinkTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -500,15 +604,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
["href"] = "/bar/css/site.css",
["asp-file-version"] = "true"
{ "rel", new HtmlString("stylesheet") },
{ "href", "/bar/css/site.css" },
{ "asp-file-version", "true" },
});
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
var output = MakeTagHelperOutput("link", attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
{ "rel", new HtmlString("stylesheet") },
});
var logger = new Mock<ILogger<LinkTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -539,16 +643,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
["href"] = "/css/site.css",
["asp-href-include"] = "**/*.css",
["asp-file-version"] = "true"
{ "rel", new HtmlString("stylesheet") },
{ "href", "/css/site.css" },
{ "asp-href-include", "**/*.css" },
{ "asp-file-version", "true" },
});
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
var output = MakeTagHelperOutput("link", attributes: new TagHelperAttributeList
{
["rel"] = new HtmlString("stylesheet"),
{ "rel", new HtmlString("stylesheet") },
});
var logger = new Mock<ILogger<LinkTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -600,10 +704,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
private static TagHelperContext MakeTagHelperContext(
IDictionary<string, object> attributes = null,
TagHelperAttributeList attributes = null,
string content = null)
{
attributes = attributes ?? new Dictionary<string, object>();
attributes = attributes ?? new TagHelperAttributeList();
return new TagHelperContext(
attributes,
@ -617,9 +721,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
}
private static TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, object> attributes = null)
private static TagHelperOutput MakeTagHelperOutput(string tagName, TagHelperAttributeList attributes = null)
{
attributes = attributes ?? new Dictionary<string, object>();
attributes = attributes ?? new TagHelperAttributeList();
return new TagHelperOutput(tagName, attributes);
}

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, null, null, null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }
},
@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, string.Empty, "value", null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
},
@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, "selected", "value", null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
},
@ -56,7 +56,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, null, "value", Enumerable.Empty<string>(),
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }
},
@ -66,7 +66,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, null, "value", new [] { string.Empty, },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }
},
@ -76,7 +76,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, string.Empty, "value", new [] { string.Empty, },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
},
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, null, "value", new [] { "value", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
},
@ -96,7 +96,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, null, "value", new [] { string.Empty, "value", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
},
@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, null, null, null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }
},
@ -116,7 +116,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, string.Empty, null, null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "" }
},
@ -126,7 +126,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, "selected", null, null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "selected" }
},
@ -136,7 +136,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, null, null, Enumerable.Empty<string>(),
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }
},
@ -146,7 +146,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, null, null, new [] { string.Empty, },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "selected" }
},
@ -156,7 +156,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, string.Empty, null, new [] { string.Empty, },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "" }
},
@ -166,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, null, null, new [] { "text", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }
},
@ -176,7 +176,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, null, null, new [] { string.Empty, "text", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "selected" }
},
@ -186,7 +186,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, null, null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }
},
@ -196,7 +196,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", string.Empty, null, null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "" }
},
@ -206,7 +206,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", "selected", null, null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "selected" }
},
@ -216,7 +216,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, null, Enumerable.Empty<string>(),
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }
},
@ -226,7 +226,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, null, new [] { string.Empty, },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }
},
@ -236,7 +236,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"HtmlEncode[[text]]", null, null, new [] { "text", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "selected" }
},
@ -246,7 +246,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", string.Empty, null, new [] { "text", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "" }
},
@ -256,7 +256,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"HtmlEncode[[text]]", null, null, new [] { string.Empty, "text", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "selected", "selected" }
},
@ -266,7 +266,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", string.Empty, "value", null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
},
@ -276,7 +276,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", "selected", "value", null,
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
},
@ -286,7 +286,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, "value", Enumerable.Empty<string>(),
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }
},
@ -296,7 +296,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, "value", new [] { string.Empty, },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }
},
@ -306,7 +306,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", string.Empty, "value", new [] { string.Empty, },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
},
@ -316,7 +316,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, "value", new [] { "text", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }
},
@ -326,7 +326,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, "value", new [] { "value", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
},
@ -336,7 +336,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"text", null, "value", new [] { string.Empty, "value", },
GetTagHelperOutput(
"not-option",
new Dictionary<string, object>
new TagHelperAttributeList
{
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
},
@ -379,7 +379,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
TagHelperOutput expectedTagHelperOutput)
{
// Arrange
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "label", "my-label" },
};
@ -388,7 +388,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
originalAttributes.Add("selected", selected);
}
var contextAttributes = new Dictionary<string, object>(originalAttributes);
var contextAttributes = new TagHelperAttributeList(originalAttributes);
if (value != null)
{
contextAttributes.Add("value", value);
@ -449,14 +449,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
TagHelperOutput ignored)
{
// Arrange
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "label", "my-label" },
{ "selected", selected },
};
var originalTagName = "not-option";
var contextAttributes = new Dictionary<string, object>
var contextAttributes = new TagHelperAttributeList
{
{ "label", "my-label" },
{ "selected", selected },
@ -510,14 +510,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
TagHelperOutput ignoredOutput)
{
// Arrange
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "label", "my-label" },
{ "selected", selected },
};
var originalTagName = "not-option";
var contextAttributes = new Dictionary<string, object>
var contextAttributes = new TagHelperAttributeList
{
{ "label", "my-label" },
{ "selected", selected },
@ -554,7 +554,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
private static TagHelperOutput GetTagHelperOutput(
string tagName, IDictionary<string, object> attributes, string content)
string tagName, TagHelperAttributeList attributes, string content)
{
var tagHelperOutput = new TagHelperOutput(tagName, attributes);
tagHelperOutput.Content.SetContent(content);

View File

@ -28,14 +28,64 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
public class ScriptTagHelperTest
{
[Theory]
[MemberData(nameof(LinkTagHelperTest.MultiAttributeSameNameData), MemberType = typeof(LinkTagHelperTest))]
public async Task HandlesMultipleAttributesSameNameCorrectly(
TagHelperAttributeList outputAttributes,
string expectedAttributeString)
{
// Arrange
var allAttributes = new TagHelperAttributeList(
outputAttributes.Concat(
new TagHelperAttributeList
{
["data-extra"] = "something",
["src"] = "/blank.js",
["asp-fallback-src"] = "http://www.example.com/blank.js",
["asp-fallback-test"] = "isavailable()",
}));
var tagHelperContext = MakeTagHelperContext(allAttributes);
var viewContext = MakeViewContext();
var combinedOutputAttributes = new TagHelperAttributeList(
outputAttributes.Concat(
new[]
{
new TagHelperAttribute("data-extra", new HtmlString("something"))
}));
var output = MakeTagHelperOutput("script", combinedOutputAttributes);
var hostingEnvironment = MakeHostingEnvironment();
var helper = new ScriptTagHelper
{
HtmlEncoder = new CommonTestEncoder(),
JavaScriptEncoder = new CommonTestEncoder(),
ViewContext = viewContext,
HostingEnvironment = hostingEnvironment,
FallbackSrc = "~/blank.js",
FallbackTestExpression = "http://www.example.com/blank.js",
Src = "/blank.js",
Cache = MakeCache(),
Logger = CreateLogger()
};
// Act
await helper.ProcessAsync(tagHelperContext, output);
// Assert
Assert.StartsWith(
"<script " + expectedAttributeString + " data-extra=\"something\" " +
"src=\"HtmlEncode[[/blank.js]]\"",
output.Content.GetContent());
}
public static TheoryData RunsWhenRequiredAttributesArePresent_Data
{
get
{
return new TheoryData<IDictionary<string, object>, Action<ScriptTagHelper>>
return new TheoryData<TagHelperAttributeList, Action<ScriptTagHelper>>
{
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-src-include"] = "*.js"
},
@ -45,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-src-include"] = "*.js",
["asp-src-exclude"] = "*.min.js"
@ -57,7 +107,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src"] = "test.js",
["asp-fallback-test"] = "isavailable()"
@ -69,7 +119,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src-include"] = "*.js",
["asp-fallback-test"] = "isavailable()"
@ -81,7 +131,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src"] = "test.js",
["asp-fallback-src-include"] = "*.js",
@ -95,7 +145,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src-include"] = "*.js",
["asp-fallback-src-exclude"] = "*.min.js",
@ -110,7 +160,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
},
// File Version
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-file-version"] = "true"
},
@ -120,7 +170,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-src-include"] = "*.js",
["asp-file-version"] = "true"
@ -132,7 +182,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-src-include"] = "*.js",
["asp-src-exclude"] = "*.min.js",
@ -146,7 +196,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src"] = "test.js",
["asp-fallback-test"] = "isavailable()",
@ -160,7 +210,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src-include"] = "*.js",
["asp-fallback-test"] = "isavailable()",
@ -174,7 +224,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src"] = "test.js",
["asp-fallback-src-include"] = "*.js",
@ -190,7 +240,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src-include"] = "*.js",
["asp-fallback-src-exclude"] = "*.min.js",
@ -212,7 +262,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[Theory]
[MemberData(nameof(RunsWhenRequiredAttributesArePresent_Data))]
public async Task RunsWhenRequiredAttributesArePresent(
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
Action<ScriptTagHelper> setProperties)
{
// Arrange
@ -245,10 +295,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
get
{
return new TheoryData<IDictionary<string, object>, Action<ScriptTagHelper>>
return new TheoryData<TagHelperAttributeList, Action<ScriptTagHelper>>
{
{
new Dictionary<string, object>
new TagHelperAttributeList
{
// This is commented out on purpose: ["asp-src-include"] = "*.js",
["asp-src-exclude"] = "*.min.js"
@ -260,7 +310,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
// This is commented out on purpose: ["asp-fallback-src"] = "test.js",
["asp-fallback-test"] = "isavailable()",
@ -272,7 +322,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
["asp-fallback-src"] = "test.js",
// This is commented out on purpose: ["asp-fallback-test"] = "isavailable()"
@ -284,7 +334,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
},
{
new Dictionary<string, object>
new TagHelperAttributeList
{
// This is commented out on purpose: ["asp-fallback-src-include"] = "test.js",
["asp-fallback-src-exclude"] = "**/*.min.js",
@ -304,7 +354,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[Theory]
[MemberData(nameof(DoesNotRunWhenARequiredAttributeIsMissing_Data))]
public void DoesNotRunWhenARequiredAttributeIsMissing(
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
Action<ScriptTagHelper> setProperties)
{
// Arrange
@ -333,7 +383,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[Theory]
[MemberData(nameof(DoesNotRunWhenARequiredAttributeIsMissing_Data))]
public async Task LogsWhenARequiredAttributeIsMissing(
IDictionary<string, object> attributes,
TagHelperAttributeList attributes,
Action<ScriptTagHelper> setProperties)
{
// Arrange
@ -431,7 +481,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var tagHelperContext = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["data-extra"] = "something",
["src"] = "/blank.js",
@ -443,7 +493,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var viewContext = MakeViewContext();
var output = MakeTagHelperOutput("src",
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["data-extra"] = "something",
["data-more"] = "else",
@ -480,12 +530,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["src"] = "/js/site.js",
["asp-src-include"] = "**/*.js"
});
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
var output = MakeTagHelperOutput("script", attributes: new TagHelperAttributeList());
var logger = new Mock<ILogger<ScriptTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
var viewContext = MakeViewContext();
@ -517,12 +567,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["src"] = "/js/site.js",
["asp-src-include"] = "**/*.js"
});
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
var output = MakeTagHelperOutput("script", attributes: new TagHelperAttributeList());
var logger = new Mock<ILogger<ScriptTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
var viewContext = MakeViewContext();
@ -555,12 +605,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["src"] = "/js/site.js",
["asp-file-version"] = "true"
});
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
var output = MakeTagHelperOutput("script", attributes: new TagHelperAttributeList());
var logger = new Mock<ILogger<ScriptTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -592,12 +642,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["src"] = "/bar/js/site.js",
["asp-file-version"] = "true"
});
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
var output = MakeTagHelperOutput("script", attributes: new TagHelperAttributeList());
var logger = new Mock<ILogger<ScriptTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -629,14 +679,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["src"] = "/js/site.js",
["asp-fallback-src-include"] = "fallback.js",
["asp-fallback-test"] = "isavailable()",
["asp-file-version"] = "true"
});
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
var output = MakeTagHelperOutput("script", attributes: new TagHelperAttributeList());
var logger = new Mock<ILogger<ScriptTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
@ -672,13 +722,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
["src"] = "/js/site.js",
["asp-src-include"] = "*.js",
["asp-file-version"] = "true"
});
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
var output = MakeTagHelperOutput("script", attributes: new TagHelperAttributeList());
var logger = new Mock<ILogger<ScriptTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
var viewContext = MakeViewContext();
@ -709,10 +759,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
private TagHelperContext MakeTagHelperContext(
IDictionary<string, object> attributes = null,
TagHelperAttributeList attributes = null,
string content = null)
{
attributes = attributes ?? new Dictionary<string, object>();
attributes = attributes ?? new TagHelperAttributeList();
return new TagHelperContext(
attributes,
@ -746,9 +796,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
return viewContext;
}
private TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, object> attributes = null)
private TagHelperOutput MakeTagHelperOutput(string tagName, TagHelperAttributeList attributes = null)
{
attributes = attributes ?? new Dictionary<string, object>();
attributes = attributes ?? new TagHelperAttributeList();
return new TagHelperOutput(tagName, attributes);
}

View File

@ -171,13 +171,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string ignored)
{
// Arrange
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
var originalPostContent = "original content";
var expectedAttributes = new Dictionary<string, object>(originalAttributes)
var expectedAttributes = new TagHelperAttributeList(originalAttributes)
{
{ "id", nameAndId.Id },
{ "name", nameAndId.Name },
@ -198,7 +198,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var modelExpression = new ModelExpression(nameAndId.Name, modelExplorer);
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -257,13 +258,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string expectedOptions)
{
// Arrange
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
var originalPostContent = "original content";
var expectedAttributes = new Dictionary<string, object>(originalAttributes)
var expectedAttributes = new TagHelperAttributeList(originalAttributes)
{
{ "id", nameAndId.Id },
{ "name", nameAndId.Name },
@ -285,7 +286,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var modelExpression = new ModelExpression(nameAndId.Name, modelExplorer);
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -358,13 +360,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string expectedOptions)
{
// Arrange
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};
var originalPostContent = "original content";
var expectedAttributes = new Dictionary<string, object>(originalAttributes)
var expectedAttributes = new TagHelperAttributeList(originalAttributes)
{
{ "id", nameAndId.Id },
{ "name", nameAndId.Name },
@ -386,7 +388,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var modelExpression = new ModelExpression(name: string.Empty, modelExplorer: modelExplorer);
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -459,12 +462,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
IEnumerable<SelectListItem> expectedItems)
{
// Arrange
var contextAttributes = new Dictionary<string, object>
var contextAttributes = new TagHelperAttributeList
{
// Provided for completeness. Select tag helper does not confirm AllAttributes set is consistent.
{ attributeName, attributeValue },
};
var originalAttributes = new Dictionary<string, object>
var originalAttributes = new TagHelperAttributeList
{
{ attributeName, attributeValue },
};
@ -545,8 +548,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
bool allowMultiple)
{
// Arrange
var contextAttributes = new Dictionary<string, object>();
var originalAttributes = new Dictionary<string, object>();
var contextAttributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>());
var originalAttributes = new TagHelperAttributeList();
var propertyName = "Property1";
var tagName = "select";

View File

@ -8,12 +8,111 @@ using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Testing;
using Microsoft.Framework.WebEncoders.Testing;
using Microsoft.Internal.Web.Utils;
using Xunit;
namespace Microsoft.AspNet.Mvc.TagHelpers
{
public class TagHelperOutputExtensionsTest
{
public static TheoryData CopyHtmlAttributeData_MultipleAttributesSameName
{
get
{
// attributeNameToCopy, allAttributes, expectedAttributes
return new TheoryData<string, TagHelperAttributeList, IEnumerable<TagHelperAttribute>>
{
{
"hello",
new TagHelperAttributeList
{
{ "hello", "world" },
{ "hello", "world2" }
},
new[]
{
new TagHelperAttribute("hello", "world"),
new TagHelperAttribute("hello", "world2"),
}
},
{
"HELLO",
new TagHelperAttributeList
{
{ "hello", "world" },
{ "hello", "world2" }
},
new[]
{
new TagHelperAttribute("hello", "world"),
new TagHelperAttribute("hello", "world2"),
}
},
{
"hello",
new TagHelperAttributeList
{
{ "HelLO", "world" },
{ "HELLO", "world2" }
},
new[]
{
new TagHelperAttribute("HelLO", "world"),
new TagHelperAttribute("HELLO", "world2"),
}
},
{
"hello",
new TagHelperAttributeList
{
{ "hello", "world" },
{ "HELLO", "world2" }
},
new[]
{
new TagHelperAttribute("hello", "world"),
new TagHelperAttribute("HELLO", "world2"),
}
},
{
"HELLO",
new TagHelperAttributeList
{
{ "HeLlO", "world" },
{ "heLLo", "world2" }
},
new[]
{
new TagHelperAttribute("HeLlO", "world"),
new TagHelperAttribute("heLLo", "world2"),
}
},
};
}
}
[Theory]
[MemberData(nameof(CopyHtmlAttributeData_MultipleAttributesSameName))]
public void CopyHtmlAttribute_CopiesAllOriginalAttributes(
string attributeNameToCopy,
TagHelperAttributeList allAttributes,
IEnumerable<TagHelperAttribute> expectedAttributes)
{
// Arrange
var output = new TagHelperOutput("p", attributes: new TagHelperAttributeList());
var context = new TagHelperContext(
allAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () => Task.FromResult<TagHelperContent>(result: null));
// Act
output.CopyHtmlAttribute(attributeNameToCopy, context);
// Assert
Assert.Equal(expectedAttributes, output.Attributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Theory]
[InlineData("hello", "world")]
[InlineData("HeLlO", "wOrLd")]
@ -22,9 +121,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
allAttributes: new TagHelperAttributeList
{
{ attributeName, attributeValue }
},
@ -36,7 +135,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.Append("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var expectedAttribute = new KeyValuePair<string, object>(attributeName, attributeValue);
var expectedAttribute = new TagHelperAttribute(attributeName, attributeValue);
// Act
tagHelperOutput.CopyHtmlAttribute("hello", tagHelperContext);
@ -53,13 +152,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var attributeName = "hello";
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>()
attributes: new TagHelperAttributeList()
{
{ attributeName, "world2" }
});
var expectedAttribute = new KeyValuePair<string, object>(attributeName, "world2");
var expectedAttribute = new TagHelperAttribute(attributeName, "world2");
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
allAttributes: new TagHelperAttributeList
{
{ attributeName, "world" }
},
@ -87,9 +186,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var invalidAttributeName = "hello2";
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
allAttributes: new TagHelperAttributeList
{
{ "hello", "world" }
},
@ -115,12 +214,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>()
attributes: new TagHelperAttributeList()
{
{ "route-Hello", "World" },
{ "Route-I", "Am" }
});
var expectedAttribute = new KeyValuePair<string, object>("type", "btn");
var expectedAttribute = new TagHelperAttribute("type", "btn");
tagHelperOutput.Attributes.Add(expectedAttribute);
var attributes = tagHelperOutput.FindPrefixedAttributes("route-");
@ -138,7 +237,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>()
attributes: new TagHelperAttributeList()
{
{ "routeHello", "World" },
{ "Routee-I", "Am" }
@ -149,20 +248,178 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Empty(attributes);
var attribute = Assert.Single(tagHelperOutput.Attributes, kvp => kvp.Key.Equals("routeHello"));
var attribute = Assert.Single(tagHelperOutput.Attributes, attr => attr.Name.Equals("routeHello"));
Assert.Equal(attribute.Value, "World");
attribute = Assert.Single(tagHelperOutput.Attributes, kvp => kvp.Key.Equals("Routee-I"));
attribute = Assert.Single(tagHelperOutput.Attributes, attr => attr.Name.Equals("Routee-I"));
Assert.Equal(attribute.Value, "Am");
}
public static TheoryData MultipleAttributeSameNameData
{
get
{
// tagBuilderAttributes, outputAttributes, expectedAttributes
return new TheoryData<Dictionary<string, string>, TagHelperAttributeList, TagHelperAttributeList>
{
{
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "class", "btn" }
},
new TagHelperAttributeList
{
{ "class", "btn2" },
{ "class", "btn3" }
},
new TagHelperAttributeList
{
{ "class", "btn2 btn" }
}
},
{
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "ClAsS", "btn" }
},
new TagHelperAttributeList
{
{ "class", "btn2" },
{ "class", "btn3" }
},
new TagHelperAttributeList
{
{ "class", "btn2 btn" }
}
},
{
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "class", "btn" }
},
new TagHelperAttributeList
{
{ "clASS", "btn2" },
{ "class", "btn3" }
},
new TagHelperAttributeList
{
{ "class", "btn2 btn" }
}
},
{
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "class", "btn" }
},
new TagHelperAttributeList
{
{ "clASS", "btn2" },
{ "CLass", "btn3" }
},
new TagHelperAttributeList
{
{ "class", "btn2 btn" }
}
},
{
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "CLASS", "btn" }
},
new TagHelperAttributeList
{
{ "clASS", "btn2" },
{ "CLass", "btn3" }
},
new TagHelperAttributeList
{
{ "class", "btn2 btn" }
}
},
{
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "CLASS", "btn" }
},
new TagHelperAttributeList
{
{ "before", "before value" },
{ "clASS", "btn2" },
{ "mid", "mid value" },
{ "CLass", "btn3" },
{ "after", "after value" },
},
new TagHelperAttributeList
{
{ "before", "before value" },
{ "class", "btn2 btn" },
{ "mid", "mid value" },
{ "after", "after value" },
}
},
{
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "A", "A Value" },
{ "CLASS", "btn" },
{ "B", "B Value" },
},
new TagHelperAttributeList
{
{ "before", "before value" },
{ "clASS", "btn2" },
{ "mid", "mid value" },
{ "CLass", "btn3" },
{ "after", "after value" },
},
new TagHelperAttributeList
{
{ "before", "before value" },
{ "class", "btn2 btn" },
{ "mid", "mid value" },
{ "after", "after value" },
{ "A", "A Value" },
{ "B", "B Value" },
}
}
};
}
}
[Theory]
[MemberData(nameof(MultipleAttributeSameNameData))]
public void MergeAttributes_ClearsDuplicateClassNameAttributes(
Dictionary<string, string> tagBuilderAttributes,
TagHelperAttributeList outputAttributes,
TagHelperAttributeList expectedAttributes)
{
// Arrange
var tagHelperOutput = new TagHelperOutput("p", outputAttributes);
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
foreach (var attr in tagBuilderAttributes)
{
tagBuilder.Attributes.Add(attr.Key, attr.Value);
}
// Act
tagHelperOutput.MergeAttributes(tagBuilder);
// Assert
Assert.Equal(
expectedAttributes,
tagHelperOutput.Attributes,
CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
public void MergeAttributes_DoesNotReplace_TagHelperOutputAttributeValues()
{
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
var expectedAttribute = new KeyValuePair<string, object>("type", "btn");
attributes: new TagHelperAttributeList());
var expectedAttribute = new TagHelperAttribute("type", "btn");
tagHelperOutput.Attributes.Add(expectedAttribute);
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
@ -182,13 +439,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
tagHelperOutput.Attributes.Add("class", "Hello");
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
tagBuilder.Attributes.Add("class", "btn");
var expectedAttribute = new KeyValuePair<string, object>("class", "Hello btn");
var expectedAttribute = new TagHelperAttribute("class", "Hello btn");
// Act
tagHelperOutput.MergeAttributes(tagBuilder);
@ -208,7 +465,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
tagHelperOutput.Attributes.Add(originalName, "Hello");
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
@ -219,7 +476,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
var attribute = Assert.Single(tagHelperOutput.Attributes);
Assert.Equal(new KeyValuePair<string, object>(originalName, "Hello btn"), attribute);
Assert.Equal(new TagHelperAttribute(originalName, "Hello btn"), attribute);
}
[Fact]
@ -228,10 +485,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
var expectedAttribute = new KeyValuePair<string, object>("visible", "val < 3");
var expectedAttribute = new TagHelperAttribute("visible", "val < 3");
tagBuilder.Attributes.Add("visible", "val < 3");
// Act
@ -248,11 +505,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
var expectedAttribute1 = new KeyValuePair<string, object>("class", "btn");
var expectedAttribute2 = new KeyValuePair<string, object>("class2", "btn");
var expectedAttribute1 = new TagHelperAttribute("class", "btn");
var expectedAttribute2 = new TagHelperAttribute("class2", "btn");
tagBuilder.Attributes.Add("class", "btn");
tagBuilder.Attributes.Add("class2", "btn");
@ -261,9 +518,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(2, tagHelperOutput.Attributes.Count);
var attribute = Assert.Single(tagHelperOutput.Attributes, kvp => kvp.Key.Equals("class"));
var attribute = Assert.Single(tagHelperOutput.Attributes, attr => attr.Name.Equals("class"));
Assert.Equal(expectedAttribute1.Value, attribute.Value);
attribute = Assert.Single(tagHelperOutput.Attributes, kvp => kvp.Key.Equals("class2"));
attribute = Assert.Single(tagHelperOutput.Attributes, attr => attr.Name.Equals("class2"));
Assert.Equal(expectedAttribute2.Value, attribute.Value);
}
@ -273,8 +530,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
var expectedAttribute = new KeyValuePair<string, object>("class", "btn");
attributes: new TagHelperAttributeList());
var expectedAttribute = new TagHelperAttribute("class", "btn");
tagHelperOutput.Attributes.Add(expectedAttribute);
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
@ -293,12 +550,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange
var tagHelperOutput = new TagHelperOutput(
"p",
attributes: new Dictionary<string, object>());
var expectedOutputAttribute = new KeyValuePair<string, object>("class", "btn");
attributes: new TagHelperAttributeList());
var expectedOutputAttribute = new TagHelperAttribute("class", "btn");
tagHelperOutput.Attributes.Add(expectedOutputAttribute);
var tagBuilder = new TagBuilder("p", new CommonTestEncoder());
var expectedBuilderAttribute = new KeyValuePair<string, object>("for", "hello");
var expectedBuilderAttribute = new TagHelperAttribute("for", "hello");
tagBuilder.Attributes.Add("for", "hello");
// Act
@ -306,10 +563,40 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(tagHelperOutput.Attributes.Count, 2);
var attribute = Assert.Single(tagHelperOutput.Attributes, kvp => kvp.Key.Equals("class"));
var attribute = Assert.Single(tagHelperOutput.Attributes, attr => attr.Name.Equals("class"));
Assert.Equal(expectedOutputAttribute.Value, attribute.Value);
attribute = Assert.Single(tagHelperOutput.Attributes, kvp => kvp.Key.Equals("for"));
attribute = Assert.Single(tagHelperOutput.Attributes, attr => attr.Name.Equals("for"));
Assert.Equal(expectedBuilderAttribute.Value, attribute.Value);
}
private class CaseSensitiveTagHelperAttributeComparer : IEqualityComparer<IReadOnlyTagHelperAttribute>
{
public readonly static CaseSensitiveTagHelperAttributeComparer Default =
new CaseSensitiveTagHelperAttributeComparer();
private CaseSensitiveTagHelperAttributeComparer()
{
}
public bool Equals(
IReadOnlyTagHelperAttribute attributeX,
IReadOnlyTagHelperAttribute attributeY)
{
return
attributeX == attributeY ||
// Normal comparer doesn't care about the Name case, in tests we do.
string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) &&
Equals(attributeX.Value, attributeY.Value);
}
public int GetHashCode(IReadOnlyTagHelperAttribute attribute)
{
return HashCodeCombiner
.Start()
.Add(attribute.Name, StringComparer.Ordinal)
.Add(attribute.Value)
.CombinedHash;
}
}
}
}

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
@ -88,7 +89,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string expectedContent)
{
// Arrange
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
{ "id", nameAndId.Id },
@ -113,7 +114,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
};
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -122,7 +124,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var htmlAttributes = new Dictionary<string, object>
var htmlAttributes = new TagHelperAttributeList
{
{ "class", "form-control" },
};

View File

@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
@ -34,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content";
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>
allAttributes: new TagHelperAttributeList
{
{ "id", "myvalidationmessage" },
{ "for", modelExpression },
@ -49,7 +50,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
{ "id", "myvalidationmessage" }
});
@ -68,13 +69,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(4, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("id"));
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("id"));
Assert.Equal("myvalidationmessage", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("class"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("class"));
Assert.Equal("field-validation-valid", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-for"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-valmsg-for"));
Assert.Equal("Name", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-replace"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-valmsg-replace"));
Assert.Equal("true", attribute.Value);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
@ -94,7 +95,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedContent = "original content";
var expectedPostContent = "original post-content";
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -105,7 +107,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
"span",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
@ -145,11 +147,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
};
var output = new TagHelperOutput(
"span",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.Content.SetContent(outputContent);
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -184,9 +187,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("span", output.TagName);
Assert.Equal(2, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-foo"));
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-foo"));
Assert.Equal("bar", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-hello"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-hello"));
Assert.Equal("world", attribute.Value);
Assert.Equal(expectedOutputContent, output.Content.GetContent());
}
@ -204,10 +207,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
};
var output = new TagHelperOutput(
"span",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -242,9 +246,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("span", output.TagName);
Assert.Equal(2, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-foo"));
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-foo"));
Assert.Equal("bar", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-hello"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-hello"));
Assert.Equal("world", attribute.Value);
Assert.Equal(expectedOutputContent, output.Content.GetContent());
}
@ -259,7 +263,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content";
var output = new TagHelperOutput(
"span",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
@ -44,7 +45,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPreContent = "original pre-content";
var expectedContent = "original content";
var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
items: new Dictionary<object, object>(),
uniqueId: "test",
getChildContentAsync: () =>
@ -55,7 +57,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
});
var output = new TagHelperOutput(
expectedTagName,
attributes: new Dictionary<string, object>
attributes: new TagHelperAttributeList
{
{ "class", "form-control" }
});
@ -74,9 +76,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal(2, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("class"));
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("class"));
Assert.Equal("form-control validation-summary-valid", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-summary"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-valmsg-summary"));
Assert.Equal("true", attribute.Value);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
@ -102,7 +104,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content";
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
@ -144,7 +146,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedContent = "original content";
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent("Content of validation summary");
@ -177,11 +179,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Assert
Assert.Equal("div", output.TagName);
Assert.Equal(3, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-foo"));
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-foo"));
Assert.Equal("bar", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-hello"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("data-hello"));
Assert.Equal("world", attribute.Value);
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("anything"));
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("anything"));
Assert.Equal("something", attribute.Value);
Assert.Equal(expectedPreContent, output.PreContent.GetContent());
Assert.Equal(expectedContent, output.Content.GetContent());
@ -201,7 +203,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content";
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent(expectedPostContent);
@ -236,7 +238,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedContent = "original content";
var output = new TagHelperOutput(
"div",
attributes: new Dictionary<string, object>());
attributes: new TagHelperAttributeList());
output.PreContent.SetContent(expectedPreContent);
output.Content.SetContent(expectedContent);
output.PostContent.SetContent("Content of validation message");

View File

@ -21,8 +21,8 @@ namespace TagHelpersWebSite.TagHelpers
{
if (Controller != null && Action != null)
{
var methodParameters = output.Attributes.ToDictionary(attribute => attribute.Key,
attribute => (object)attribute.Value);
var methodParameters = output.Attributes.ToDictionary(attribute => attribute.Name,
attribute => attribute.Value);
// We remove all attributes from the resulting HTML element because they're supposed to
// be parameters to our final href value.