diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
index dfc7f42b31..8934baca73 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
@@ -254,15 +254,30 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private void GenerateCheckBox(ModelExplorer modelExplorer, TagHelperOutput output)
{
- if (typeof(bool) != modelExplorer.ModelType)
+ if (modelExplorer.ModelType == typeof(string))
+ {
+ if (modelExplorer.Model != null)
+ {
+ bool potentialBool;
+ if (!bool.TryParse(modelExplorer.Model.ToString(), out potentialBool))
+ {
+ throw new InvalidOperationException(Resources.FormatInputTagHelper_InvalidStringResult(
+ ForAttributeName,
+ modelExplorer.Model.ToString(),
+ typeof(bool).FullName));
+ }
+ }
+ }
+ else if (modelExplorer.ModelType != typeof(bool))
{
throw new InvalidOperationException(Resources.FormatInputTagHelper_InvalidExpressionResult(
- "",
- ForAttributeName,
- modelExplorer.ModelType.FullName,
- typeof(bool).FullName,
- "type",
- "checkbox"));
+ "",
+ ForAttributeName,
+ modelExplorer.ModelType.FullName,
+ typeof(bool).FullName,
+ typeof(string).FullName,
+ "type",
+ "checkbox"));
}
// Prepare to move attributes from current element to generated just below.
diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Properties/Resources.Designer.cs
index 5ef947f86e..094e3d2d0a 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Properties/Resources.Designer.cs
@@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
///
- /// Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' if '{4}' is '{5}'.
+ /// Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' or '{4}' that can be parsed as a '{3}' if '{5}' is '{6}'.
///
internal static string InputTagHelper_InvalidExpressionResult
{
@@ -67,11 +67,27 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
///
- /// Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' if '{4}' is '{5}'.
+ /// Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' or '{4}' that can be parsed as a '{3}' if '{5}' is '{6}'.
///
- internal static string FormatInputTagHelper_InvalidExpressionResult(object p0, object p1, object p2, object p3, object p4, object p5)
+ internal static string FormatInputTagHelper_InvalidExpressionResult(object p0, object p1, object p2, object p3, object p4, object p5, object p6)
{
- return string.Format(CultureInfo.CurrentCulture, GetString("InputTagHelper_InvalidExpressionResult"), p0, p1, p2, p3, p4, p5);
+ return string.Format(CultureInfo.CurrentCulture, GetString("InputTagHelper_InvalidExpressionResult"), p0, p1, p2, p3, p4, p5, p6);
+ }
+
+ ///
+ /// Unexpected expression result value '{1}' for {0}. '{1}' cannot be parsed as a '{2}'.
+ ///
+ internal static string InputTagHelper_InvalidStringResult
+ {
+ get { return GetString("InputTagHelper_InvalidStringResult"); }
+ }
+
+ ///
+ /// Unexpected expression result value '{1}' for {0}. '{1}' cannot be parsed as a '{2}'.
+ ///
+ internal static string FormatInputTagHelper_InvalidStringResult(object p0, object p1, object p2)
+ {
+ return string.Format(CultureInfo.CurrentCulture, GetString("InputTagHelper_InvalidStringResult"), p0, p1, p2);
}
///
diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Resources.resx b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Resources.resx
index ade3082337..48ad0dca73 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Resources.resx
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Resources.resx
@@ -127,7 +127,10 @@
Cannot override the '{1}' attribute for {0}. A {0} with a specified '{1}' must not have attributes starting with '{7}' or an '{2}', '{3}', '{4}', '{5}', or '{6}' attribute.
- Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' if '{4}' is '{5}'.
+ Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' or '{4}' that can be parsed as a '{3}' if '{5}' is '{6}'.
+
+
+ Unexpected expression result value '{1}' for {0}. '{1}' cannot be parsed as a '{2}'.'{1}' must not be null for {0} if '{2}' is '{3}'.
diff --git a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs
index 191fc2d914..6e443c5c5f 100644
--- a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs
@@ -113,6 +113,142 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Assert.Null(output.TagName); // Cleared
}
+ [Theory]
+ [InlineData("bad")]
+ [InlineData("notbool")]
+ public void CheckBoxHandlesNonParsableStringsAsBoolsCorrectly(
+ string possibleBool)
+ {
+ // Arrange
+ const string content = "original content";
+ const string tagName = "input";
+ const string forAttributeName = "asp-for";
+
+ var expected = Resources.FormatInputTagHelper_InvalidStringResult(
+ forAttributeName,
+ possibleBool,
+ typeof(bool).FullName);
+
+ var attributes = new TagHelperAttributeList
+ {
+ { "class", "form-control" },
+ };
+
+ var context = new TagHelperContext(
+ allAttributes: new TagHelperAttributeList(
+ Enumerable.Empty()),
+ items: new Dictionary