diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs index e167fc52c6..d0cae73f5e 100644 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs @@ -122,6 +122,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers return string.Format(CultureInfo.CurrentCulture, GetString("InvalidEnumArgument"), p0, p1, p2); } + /// + /// The attribute '{0}' does not exist in the {1}. + /// + internal static string TagHelperOutput_AttributeDoesNotExist + { + get { return GetString("TagHelperOutput_AttributeDoesNotExist"); } + } + + /// + /// The attribute '{0}' does not exist in the {1}. + /// + internal static string FormatTagHelperOutput_AttributeDoesNotExist(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("TagHelperOutput_AttributeDoesNotExist"), p0, p1); + } + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx b/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx index 1aa82d190f..8d7adbdb7d 100644 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx +++ b/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx @@ -138,4 +138,7 @@ The value of argument '{0}' ({1}) is invalid for Enum type '{2}'. + + The attribute '{0}' does not exist in the {1}. + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOutputExtensions.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOutputExtensions.cs index f72506bad2..e6a25d408a 100644 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOutputExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOutputExtensions.cs @@ -35,8 +35,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { // 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.First( + var entry = context.AllAttributes.FirstOrDefault( attribute => attribute.Key.Equals(attributeName, StringComparison.OrdinalIgnoreCase)); + + if (entry.Equals(default(KeyValuePair))) + { + throw new ArgumentException( + Resources.FormatTagHelperOutput_AttributeDoesNotExist(attributeName, nameof(TagHelperContext)), + nameof(attributeName)); + } + tagHelperOutput.Attributes.Add(entry.Key, entry.Value); } } diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs index 43cef4b14a..4fa6c957d0 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Razor.Runtime.TagHelpers; +using Microsoft.AspNet.Testing; using Microsoft.Framework.WebEncoders; using Xunit; @@ -79,6 +80,35 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal(expectedAttribute, attribute); } + [Fact] + public void CopyHtmlAttribute_ThrowsWhenUnknownAttribute() + { + // Arrange + var invalidAttributeName = "hello2"; + var tagHelperOutput = new TagHelperOutput( + "p", + attributes: new Dictionary()); + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(StringComparer.Ordinal) + { + { "hello", "world" } + }, + items: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => + { + var tagHelperContent = new DefaultTagHelperContent(); + tagHelperContent.Append("Something"); + return Task.FromResult(tagHelperContent); + }); + + // Act & Assert + ExceptionAssert.ThrowsArgument( + () => tagHelperOutput.CopyHtmlAttribute(invalidAttributeName, tagHelperContext), + "attributeName", + "The attribute 'hello2' does not exist in the TagHelperContext."); + } + [Fact] public void RemoveRange_RemovesProvidedAttributes() {