diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs
index 49bda15739..08c30ac708 100644
--- a/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs
@@ -15,6 +15,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
///
/// implementation targeting <input> elements with an asp-for attribute.
///
+ [TargetElement("input", Attributes = ForAttributeName)]
public class InputTagHelper : TagHelper
{
private const string ForAttributeName = "asp-for";
@@ -121,93 +122,79 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
output.CopyHtmlAttribute(nameof(Value), context);
}
- if (For == null)
+ // Note null or empty For.Name is allowed because TemplateInfo.HtmlFieldPrefix may be sufficient.
+ // IHtmlGenerator will enforce name requirements.
+ var metadata = For.Metadata;
+ var modelExplorer = For.ModelExplorer;
+ if (metadata == null)
{
- // Regular HTML element. Just make sure Format wasn't specified.
- if (Format != null)
- {
- throw new InvalidOperationException(Resources.FormatInputTagHelper_UnableToFormat(
- "",
- ForAttributeName,
- FormatAttributeName));
- }
+ throw new InvalidOperationException(Resources.FormatTagHelpers_NoProvidedMetadata(
+ "",
+ ForAttributeName,
+ nameof(IModelMetadataProvider),
+ For.Name));
+ }
+
+ string inputType;
+ string inputTypeHint;
+ if (string.IsNullOrEmpty(InputTypeName))
+ {
+ // Note GetInputType never returns null.
+ inputType = GetInputType(modelExplorer, out inputTypeHint);
}
else
{
- // Note null or empty For.Name is allowed because TemplateInfo.HtmlFieldPrefix may be sufficient.
- // IHtmlGenerator will enforce name requirements.
- var metadata = For.Metadata;
- var modelExplorer = For.ModelExplorer;
- if (metadata == null)
- {
- throw new InvalidOperationException(Resources.FormatTagHelpers_NoProvidedMetadata(
- "",
- ForAttributeName,
- nameof(IModelMetadataProvider),
- For.Name));
- }
+ inputType = InputTypeName.ToLowerInvariant();
+ inputTypeHint = null;
+ }
- string inputType;
- string inputTypeHint;
- if (string.IsNullOrEmpty(InputTypeName))
- {
- // Note GetInputType never returns null.
- inputType = GetInputType(modelExplorer, out inputTypeHint);
- }
- else
- {
- inputType = InputTypeName.ToLowerInvariant();
- inputTypeHint = null;
- }
+ // inputType may be more specific than default the generator chooses below.
+ if (!output.Attributes.ContainsKey("type"))
+ {
+ output.Attributes["type"] = inputType;
+ }
- // inputType may be more specific than default the generator chooses below.
- if (!output.Attributes.ContainsKey("type"))
- {
- output.Attributes["type"] = inputType;
- }
+ TagBuilder tagBuilder;
+ switch (inputType)
+ {
+ case "checkbox":
+ GenerateCheckBox(modelExplorer, output);
+ return;
- TagBuilder tagBuilder;
- switch (inputType)
- {
- case "checkbox":
- GenerateCheckBox(modelExplorer, output);
- return;
+ case "hidden":
+ tagBuilder = Generator.GenerateHidden(
+ ViewContext,
+ modelExplorer,
+ For.Name,
+ value: For.Model,
+ useViewData: false,
+ htmlAttributes: null);
+ break;
- case "hidden":
- tagBuilder = Generator.GenerateHidden(
- ViewContext,
- modelExplorer,
- For.Name,
- value: For.Model,
- useViewData: false,
- htmlAttributes: null);
- break;
+ case "password":
+ tagBuilder = Generator.GeneratePassword(
+ ViewContext,
+ modelExplorer,
+ For.Name,
+ value: null,
+ htmlAttributes: null);
+ break;
- case "password":
- tagBuilder = Generator.GeneratePassword(
- ViewContext,
- modelExplorer,
- For.Name,
- value: null,
- htmlAttributes: null);
- break;
+ case "radio":
+ tagBuilder = GenerateRadio(modelExplorer);
+ break;
- case "radio":
- tagBuilder = GenerateRadio(modelExplorer);
- break;
+ default:
+ tagBuilder = GenerateTextBox(modelExplorer, inputTypeHint, inputType);
+ break;
+ }
- default:
- tagBuilder = GenerateTextBox(modelExplorer, inputTypeHint, inputType);
- break;
- }
-
- if (tagBuilder != null)
- {
- // This TagBuilder contains the one element of interest. Since this is not the "checkbox"
- // special-case, output is a self-closing element no longer guarunteed.
- output.MergeAttributes(tagBuilder);
- output.Content.Append(tagBuilder.InnerHtml);
- }
+ if (tagBuilder != null)
+ {
+ // This TagBuilder contains the one element of interest. Since this is not the "checkbox"
+ // special-case, output is a self-closing element no longer guarunteed.
+ output.MergeAttributes(tagBuilder);
+ output.Content.Append(tagBuilder.InnerHtml);
}
}
diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/LabelTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/LabelTagHelper.cs
index e691c018b0..eaedb3f2cd 100644
--- a/src/Microsoft.AspNet.Mvc.TagHelpers/LabelTagHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.TagHelpers/LabelTagHelper.cs
@@ -10,6 +10,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
///
/// implementation targeting <label> elements with an asp-for attribute.
///
+ [TargetElement("label", Attributes = ForAttributeName)]
public class LabelTagHelper : TagHelper
{
private const string ForAttributeName = "asp-for";
@@ -32,34 +33,32 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
/// Does nothing if is null.
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
- if (For != null)
+ var tagBuilder = Generator.GenerateLabel(
+ ViewContext,
+ For.ModelExplorer,
+ For.Name,
+ labelText: null,
+ htmlAttributes: null);
+
+ if (tagBuilder != null)
{
- var tagBuilder = Generator.GenerateLabel(ViewContext,
- For.ModelExplorer,
- For.Name,
- labelText: null,
- htmlAttributes: null);
+ output.MergeAttributes(tagBuilder);
- if (tagBuilder != null)
+ // We check for whitespace to detect scenarios such as:
+ //
+ if (!output.IsContentModified)
{
- output.MergeAttributes(tagBuilder);
+ var childContent = await context.GetChildContentAsync();
- // We check for whitespace to detect scenarios such as:
- //
- if (!output.IsContentModified)
+ if (childContent.IsWhiteSpace)
{
- var childContent = await context.GetChildContentAsync();
-
- if (childContent.IsWhiteSpace)
- {
- // Provide default label text since there was nothing useful in the Razor source.
- output.Content.SetContent(tagBuilder.InnerHtml);
- }
- else
- {
- output.Content.SetContent(childContent);
- }
+ // Provide default label text since there was nothing useful in the Razor source.
+ output.Content.SetContent(tagBuilder.InnerHtml);
+ }
+ else
+ {
+ output.Content.SetContent(childContent);
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs
index c46e3e4940..53da161a39 100644
--- a/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs
@@ -74,22 +74,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
return string.Format(CultureInfo.CurrentCulture, GetString("InputTagHelper_InvalidExpressionResult"), p0, p1, p2, p3, p4, p5);
}
- ///
- /// Unable to format without a '{1}' expression for {0}. '{2}' must be null if '{1}' is null.
- ///
- internal static string InputTagHelper_UnableToFormat
- {
- get { return GetString("InputTagHelper_UnableToFormat"); }
- }
-
- ///
- /// Unable to format without a '{1}' expression for {0}. '{2}' must be null if '{1}' is null.
- ///
- internal static string FormatInputTagHelper_UnableToFormat(object p0, object p1, object p2)
- {
- return string.Format(CultureInfo.CurrentCulture, GetString("InputTagHelper_UnableToFormat"), p0, p1, p2);
- }
-
///
/// '{1}' must not be null for {0} if '{2}' is '{3}'.
///
diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx b/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx
index ce38a162fc..6a35258fbb 100644
--- a/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx
+++ b/src/Microsoft.AspNet.Mvc.TagHelpers/Resources.resx
@@ -129,9 +129,6 @@
Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' if '{4}' is '{5}'.
-
- Unable to format without a '{1}' expression for {0}. '{2}' must be null if '{1}' is null.
-
'{1}' must not be null for {0} if '{2}' is '{3}'.
diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationMessageTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationMessageTagHelper.cs
index 2312c8c7ec..f7a9102cf1 100644
--- a/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationMessageTagHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationMessageTagHelper.cs
@@ -8,10 +8,10 @@ using Microsoft.AspNet.Razor.Runtime.TagHelpers;
namespace Microsoft.AspNet.Mvc.TagHelpers
{
///
- /// implementation targeting <span> elements with an asp-validation-for
+ /// implementation targeting any HTML element with an asp-validation-for
/// attribute.
///
- [TargetElement("span")]
+ [TargetElement("span", Attributes = ValidationForAttributeName)]
public class ValidationMessageTagHelper : TagHelper
{
private const string ValidationForAttributeName = "asp-validation-for";
diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationSummaryTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationSummaryTagHelper.cs
index 2da0498a95..ab861e509b 100644
--- a/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationSummaryTagHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.TagHelpers/ValidationSummaryTagHelper.cs
@@ -8,10 +8,10 @@ using Microsoft.AspNet.Razor.Runtime.TagHelpers;
namespace Microsoft.AspNet.Mvc.TagHelpers
{
///
- /// implementation targeting <div> elements with an asp-validation-summary
+ /// implementation targeting any HTML element with an asp-validation-summary
/// attribute.
///
- [TargetElement("div")]
+ [TargetElement("div", Attributes = ValidationSummaryAttributeName)]
public class ValidationSummaryTagHelper : TagHelper
{
private const string ValidationSummaryAttributeName = "asp-validation-summary";
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.Invalid.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.Invalid.html
index 7cf694c9e5..44f32743b6 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.Invalid.html
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.Invalid.html
@@ -69,7 +69,7 @@
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.html
index f68288557e..120e91115b 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.html
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/TagHelpersWebSite.Employee.Create.html
@@ -67,7 +67,7 @@
diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs
index f1351e6f4d..05c644d947 100644
--- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs
+++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs
@@ -617,62 +617,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal(expectedTagName, output.TagName);
}
- [Fact]
- public async Task TagHelper_RestoresTypeAndValue_IfForNotBound()
- {
- // Arrange
- var expectedAttributes = new Dictionary
- {
- { "class", "form-control" },
- { "type", "datetime" },
- { "value", "2014-10-15T23:24:19.000-7:00" },
- };
- var expectedPreContent = "original pre-content";
- var expectedContent = "original content";
- var expectedPostContent = "original post-content";
- var expectedTagName = "input";
-
- var tagHelperContext = new TagHelperContext(
- allAttributes: new Dictionary(),
- items: new Dictionary