diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/Properties/Resources.Designer.cs index 7b8b93dd4d..4c26418900 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/Properties/Resources.Designer.cs @@ -762,6 +762,22 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures return string.Format(CultureInfo.CurrentCulture, GetString("RemoteAttribute_RemoteValidationFailed"), p0); } + /// + /// The name of an HTML field cannot be null or empty. Instead use methods {0}.{1} or {2}.{3} with a non-empty {4} argument value. + /// + internal static string HtmlGenerator_FieldNameCannotBeNullOrEmpty + { + get { return GetString("HtmlGenerator_FieldNameCannotBeNullOrEmpty"); } + } + + /// + /// The name of an HTML field cannot be null or empty. Instead use methods {0}.{1} or {2}.{3} with a non-empty {4} argument value. + /// + internal static string FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty(object p0, object p1, object p2, object p3, object p4) + { + return string.Format(CultureInfo.CurrentCulture, GetString("HtmlGenerator_FieldNameCannotBeNullOrEmpty"), p0, p1, p2, p3, p4); + } + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/Rendering/Html/DefaultHtmlGenerator.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/Rendering/Html/DefaultHtmlGenerator.cs index ea816588e8..9573dce101 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/Rendering/Html/DefaultHtmlGenerator.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/Rendering/Html/DefaultHtmlGenerator.cs @@ -413,8 +413,15 @@ namespace Microsoft.AspNet.Mvc.Rendering var fullName = GetFullHtmlFieldName(viewContext, expression); if (string.IsNullOrEmpty(fullName)) { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(expression)); - } + throw new ArgumentException( + Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty( + typeof(IHtmlHelper).FullName, + nameof(IHtmlHelper.Editor), + typeof(IHtmlHelper<>).FullName, + nameof(IHtmlHelper.EditorFor), + "htmlFieldName"), + nameof(expression)); + } // If we got a null selectList, try to use ViewData to get the list of items. if (selectList == null) @@ -483,7 +490,14 @@ namespace Microsoft.AspNet.Mvc.Rendering var fullName = GetFullHtmlFieldName(viewContext, expression); if (string.IsNullOrEmpty(fullName)) { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(expression)); + throw new ArgumentException( + Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty( + typeof(IHtmlHelper).FullName, + nameof(IHtmlHelper.Editor), + typeof(IHtmlHelper<>).FullName, + nameof(IHtmlHelper.EditorFor), + "htmlFieldName"), + nameof(expression)); } ModelState modelState; @@ -563,7 +577,14 @@ namespace Microsoft.AspNet.Mvc.Rendering var fullName = GetFullHtmlFieldName(viewContext, expression); if (string.IsNullOrEmpty(fullName)) { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(expression)); + throw new ArgumentException( + Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty( + typeof(IHtmlHelper).FullName, + nameof(IHtmlHelper.Editor), + typeof(IHtmlHelper<>).FullName, + nameof(IHtmlHelper.EditorFor), + "htmlFieldName"), + nameof(expression)); } var formContext = viewContext.ClientValidationEnabled ? viewContext.FormContext : null; @@ -738,7 +759,14 @@ namespace Microsoft.AspNet.Mvc.Rendering var fullName = GetFullHtmlFieldName(viewContext, expression); if (string.IsNullOrEmpty(fullName)) { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(expression)); + throw new ArgumentException( + Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty( + typeof(IHtmlHelper).FullName, + nameof(IHtmlHelper.Editor), + typeof(IHtmlHelper<>).FullName, + nameof(IHtmlHelper.EditorFor), + "htmlFieldName"), + nameof(expression)); } var type = allowMultiple ? typeof(string[]) : typeof(string); @@ -969,7 +997,14 @@ namespace Microsoft.AspNet.Mvc.Rendering var fullName = GetFullHtmlFieldName(viewContext, expression); if (string.IsNullOrEmpty(fullName)) { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(expression)); + throw new ArgumentException( + Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty( + typeof(IHtmlHelper).FullName, + nameof(IHtmlHelper.Editor), + typeof(IHtmlHelper<>).FullName, + nameof(IHtmlHelper.EditorFor), + "htmlFieldName"), + nameof(expression)); } var tagBuilder = new TagBuilder("input", _htmlEncoder); diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/Resources.resx b/src/Microsoft.AspNet.Mvc.ViewFeatures/Resources.resx index 0c6b0b1f67..7b1e86fddd 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/Resources.resx +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/Resources.resx @@ -259,4 +259,7 @@ '{0}' is invalid. + + The name of an HTML field cannot be null or empty. Instead use methods {0}.{1} or {2}.{3} with a non-empty {4} argument value. + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/DefaultHtmlGeneratorTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/DefaultHtmlGeneratorTest.cs index 78f594f828..e2752bdbe2 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/DefaultHtmlGeneratorTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/DefaultHtmlGeneratorTest.cs @@ -60,6 +60,116 @@ namespace Microsoft.AspNet.Mvc.Rendering Assert.Null(result); } + [Fact] + public void GetCurrentValues_WithNullExpression_Throws() + { + // Arrange + var metadataProvider = new TestModelMetadataProvider(); + var htmlGenerator = GetGenerator(metadataProvider); + var viewContext = GetViewContext(model: null, metadataProvider: metadataProvider); + var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), model: null); + + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; + + // Act and assert + var ex = Assert.Throws( + "expression", + () => htmlGenerator.GetCurrentValues( + viewContext, + modelExplorer, + expression: null, + allowMultiple: true)); + + Assert.Equal(expected, ex.Message); + } + + [Fact] + public void GenerateSelect_WithNullExpression_Throws() + { + // Arrange + var metadataProvider = new TestModelMetadataProvider(); + var htmlGenerator = GetGenerator(metadataProvider); + var viewContext = GetViewContext(model: null, metadataProvider: metadataProvider); + var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), model: null); + + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; + + // Act and assert + var ex = Assert.Throws( + "expression", + () => htmlGenerator.GenerateSelect( + viewContext, + modelExplorer, + "label", + null, + new List(), + true, + null)); + + Assert.Equal(expected, ex.Message); + } + + [Fact] + public void GenerateTextArea_WithNullExpression_Throws() + { + // Arrange + var metadataProvider = new TestModelMetadataProvider(); + var htmlGenerator = GetGenerator(metadataProvider); + var viewContext = GetViewContext(model: null, metadataProvider: metadataProvider); + var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), model: null); + + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; + + // Act and assert + var ex = Assert.Throws( + "expression", + () => htmlGenerator.GenerateTextArea( + viewContext, + modelExplorer, + null, + 1, + 1, + null)); + + Assert.Equal(expected, ex.Message); + } + + [Fact] + public void GenerateValidationMessage_WithNullExpression_Throws() + { + // Arrange + var metadataProvider = new TestModelMetadataProvider(); + var htmlGenerator = GetGenerator(metadataProvider); + var viewContext = GetViewContext(model: null, metadataProvider: metadataProvider); + var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), model: null); + + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; + + // Act and assert + var ex = Assert.Throws( + "expression", + () => htmlGenerator.GenerateValidationMessage( + viewContext, + null, + "Message", + "tag", + null)); + + Assert.Equal(expected, ex.Message); + } + [Theory] [InlineData(false)] [InlineData(true)] diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperCheckboxTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperCheckboxTest.cs index 3fbb87512b..a352f5bcd4 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperCheckboxTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperCheckboxTest.cs @@ -86,6 +86,25 @@ namespace Microsoft.AspNet.Mvc.Rendering Assert.Equal(expected, ex.Message); } + [Fact] + public void CheckBoxWithNullExpressionThrows() + { + // Arrange + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; + + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData()); + + // Act & Assert + var ex = Assert.Throws( + "expression", + () => helper.CheckBox(null, isChecked: true, htmlAttributes: null)); + + Assert.Equal(expected, ex.Message); + } + [Fact] public void CheckBoxCheckedWithOnlyName_GeneratesExpectedValue() { diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperHiddenTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperHiddenTest.cs index 192f3133de..34825ec401 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperHiddenTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperHiddenTest.cs @@ -403,10 +403,16 @@ namespace Microsoft.AspNet.Mvc.Rendering { { "class", "some-class"} }; + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; // Act and Assert - ExceptionAssert.ThrowsArgumentNullOrEmpty(() => helper.Hidden(string.Empty, string.Empty, attributes), - "expression"); + ExceptionAssert.ThrowsArgument( + () => helper.Hidden(string.Empty, string.Empty, attributes), + "expression", + expected); } [Fact] diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs index 30ea2c767c..450560a915 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs @@ -128,10 +128,16 @@ namespace Microsoft.AspNet.Mvc.Rendering var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); var name = string.Empty; var value = string.Empty; + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; // Act and Assert - ExceptionAssert.ThrowsArgumentNullOrEmpty(() => helper.Password(name, value, htmlAttributes: null), - "expression"); + ExceptionAssert.ThrowsArgument( + () => helper.Password(name, value, htmlAttributes: null), + "expression", + expected); } [Fact] diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperSelectTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperSelectTest.cs index ed2340300c..dee880a29d 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperSelectTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperSelectTest.cs @@ -362,6 +362,27 @@ namespace Microsoft.AspNet.Mvc.Rendering Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } + [Theory] + [MemberData(nameof(DropDownListDataSet))] + public void DropDownList_WithNullExpression_Throws( + IEnumerable selectList, + string expectedHtml, + string ignoredHtml) + { + // Arrange + var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + + Environment.NewLine + "Parameter name: expression"; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(); + + // Act & Assert + var ex = Assert.Throws( + "expression", + () => helper.DropDownList(null, selectList: null, optionLabel: null, htmlAttributes: null)); + Assert.Equal(expected, ex.Message); + } + [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownList_WithModelValue_GeneratesExpectedValue(