diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperDisplayExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperDisplayExtensionsTest.cs
new file mode 100644
index 0000000000..d1c294c1e8
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperDisplayExtensionsTest.cs
@@ -0,0 +1,360 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc.TestCommon;
+using Microsoft.AspNetCore.Mvc.ViewEngines;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.Rendering
+{
+ public class HtmlHelperDisplayExtensionsTest
+ {
+ [Fact]
+ public void DisplayHelpers_FindsModel_WhenViewDataIsNotSet()
+ {
+ // Arrange
+ var expected = $"
HtmlEncode[[SomeProperty]]
{Environment.NewLine}" +
+ $"HtmlEncode[[PropValue]]
{Environment.NewLine}";
+ var model = new SomeModel
+ {
+ SomeProperty = "PropValue"
+ };
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.Display(expression: string.Empty);
+ var displayNullResult = helper.Display(expression: null); // null is another alias for current model
+ var displayForResult = helper.DisplayFor(m => m);
+ var displayForModelResult = helper.DisplayForModel();
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayResult));
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayNullResult));
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayForResult));
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayForModelResult));
+ }
+
+ [Fact]
+ public void Display_UsesAdditionalViewData()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.Display(expression: "SomeProperty", additionalViewData: new { SomeProperty = "ViewDataValue" });
+
+ // Assert
+ Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void Display_UsesTemplateName()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", Mock.Of()))
+ .Verifiable();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.Display(expression: "SomeProperty", templateName: "SomeTemplate");
+
+ // Assert
+ viewEngine.Verify();
+ }
+
+ [Fact]
+ public void Display_UsesTemplateNameAndAdditionalViewData()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.Display(
+ expression: "SomeProperty",
+ templateName: "SomeTemplate",
+ additionalViewData: new { SomeProperty = "ViewDataValue" });
+
+ // Assert
+ Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void Display_UsesTemplateNameAndHtmlFieldName()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.Display(
+ expression: "SomeProperty",
+ templateName: "SomeTemplate",
+ htmlFieldName: "SomeField");
+
+ // Assert
+ Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void DisplayFor_UsesAdditionalViewData()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayFor(expression: m => m.SomeProperty, additionalViewData: new { SomeProperty = "ViewDataValue" });
+
+ // Assert
+ Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void DisplayFor_UsesTemplateName()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", Mock.Of()))
+ .Verifiable();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayFor(expression: m => m.SomeProperty, templateName: "SomeTemplate");
+
+ // Assert
+ viewEngine.Verify();
+ }
+
+ [Fact]
+ public void DisplayFor_UsesTemplateNameAndAdditionalViewData()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayFor(
+ expression: m => m.SomeProperty,
+ templateName: "SomeTemplate",
+ additionalViewData: new { SomeProperty = "ViewDataValue" });
+
+ // Assert
+ Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void DisplayFor_UsesTemplateNameAndHtmlFieldName()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayFor(
+ expression: m => m.SomeProperty,
+ templateName: "SomeTemplate",
+ htmlFieldName: "SomeField");
+
+ // Assert
+ Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void DisplayForModel_UsesAdditionalViewData()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayForModel(additionalViewData: new { SomeProperty = "ViewDataValue" });
+
+ // Assert
+ Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void DisplayForModel_UsesTemplateName()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", Mock.Of()))
+ .Verifiable();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayForModel(templateName: "SomeTemplate");
+
+ // Assert
+ viewEngine.Verify();
+ }
+
+ [Fact]
+ public void DisplayForModel_UsesTemplateNameAndAdditionalViewData()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayForModel(
+ templateName: "SomeTemplate",
+ additionalViewData: new { SomeProperty = "ViewDataValue" });
+
+ // Assert
+ Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ [Fact]
+ public void DisplayForModel_UsesTemplateNameAndHtmlFieldName()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
+ .Returns(Task.FromResult(0));
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine
+ .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false))
+ .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty()));
+ viewEngine
+ .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
+ .Returns(ViewEngineResult.Found("SomeView", view.Object));
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
+
+ // Act
+ var displayResult = helper.DisplayForModel(
+ templateName: "SomeTemplate",
+ htmlFieldName: "SomeField");
+
+ // Assert
+ Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
+ }
+
+ private class SomeModel
+ {
+ public string SomeProperty { get; set; }
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs
index 41a3a9654f..96a3e2edc9 100644
--- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperPasswordTest.cs
@@ -439,6 +439,61 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
return viewData;
}
+ public static TheoryData PasswordFor_IgnoresExpressionValueForComplexExpressionsData
+ {
+ get
+ {
+ return new TheoryData>, string>
+ {
+ {
+ model => model.Property3["key"],
+ @""
+ },
+ {
+ model => model.Property4.Property5,
+ @""
+ },
+ {
+ model => model.Property4.Property6[0],
+ @""
+ }
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(PasswordFor_IgnoresExpressionValueForComplexExpressionsData))]
+ public void PasswordFor_ComplexExpressions_IgnoresValueFromViewDataModelStateAndModel(
+ Expression> expression,
+ string expected)
+ {
+ // Arrange
+ var model = new PasswordModel();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+ helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
+
+ helper.ViewData.ModelState.SetModelValue("pre.Property3[key]", "MProp3Val", "MProp3Val");
+ helper.ViewData.ModelState.SetModelValue("pre.Property4.Property5", "MProp5Val", "MProp5Val");
+ helper.ViewData.ModelState.SetModelValue("pre.Property4.Property6[0]", "MProp6Val", "MProp6Val");
+
+ helper.ViewData["pre.Property3[key]"] = "VDProp3Val";
+ helper.ViewData["pre.Property4.Property5"] = "VDProp5Val";
+ helper.ViewData["pre.Property4.Property6"] = "VDProp6Val";
+
+ helper.ViewData.Model.Property3["key"] = "Prop3Val";
+ helper.ViewData.Model.Property4.Property5 = "Prop5Val";
+ helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
+
+ // Act
+ var result = helper.PasswordFor(expression);
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
+ }
+
public class PasswordModel
{
public string Property1 { get; set; }
diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTest.cs
index 5b89516068..180dea3415 100644
--- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTest.cs
@@ -286,6 +286,53 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
Assert.Equal(expectedString, result.ToString());
}
+ [Theory]
+ [InlineData("SomeName", "SomeName")]
+ [InlineData("Obj1.Prop1", "Obj1_Prop1")]
+ [InlineData("Obj1.Prop1[0]", "Obj1_Prop1_0_")]
+ [InlineData("Obj1.Prop1[0].Prop2", "Obj1_Prop1_0__Prop2")]
+ public void GenerateIdFromName_ReturnsExpectedValues(string fullname, string expected)
+ {
+ // Arrange
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper();
+
+ // Act
+ var result = helper.GenerateIdFromName(fullname);
+
+ // Assert
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [InlineData(FormMethod.Get, "get")]
+ [InlineData(FormMethod.Post, "post")]
+ [InlineData((FormMethod)42, "post")]
+ public void GetFormMethodString_ReturnsExpectedValues(FormMethod method, string expected)
+ {
+ // Act
+ var result = HtmlHelper.GetFormMethodString(method);
+
+ // Assert
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [InlineData("-{0}-", "-boldFromObject-")]
+ [InlineData("-%{0}%-", "-%boldFromObject%-")]
+ [InlineData("-=={0}=={0}==-", "-==boldFromObject==boldFromObject==-")]
+ public void FormatValue_ReturnsExpectedValues(string format, string expected)
+ {
+ // Arrange
+ var value = new ObjectWithToStringOverride();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper();
+
+ // Act
+ var result = helper.FormatValue(value, format);
+
+ // Assert
+ Assert.Equal(expected, result);
+ }
+
private class ObjectWithToStringOverride
{
public override string ToString()
diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextAreaTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextAreaTest.cs
index e9014ad9a8..a00633e372 100644
--- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextAreaTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextAreaTest.cs
@@ -2,13 +2,15 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc.TestCommon;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Rendering
{
- public class HtmlHelperTextBoxAreaTest
+ public class HtmlHelperTextAreaTest
{
[Fact]
public void TextAreaFor_GeneratesPlaceholderAttribute_WhenDisplayAttributePromptIsSetAndTypeIsValid()
@@ -40,6 +42,125 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
Assert.DoesNotContain(@"placeholder=""HtmlEncode[[placeholder]]""", result, StringComparison.Ordinal);
}
+ public static TheoryData TextAreaFor_UsesModelValueForComplexExpressionsData
+ {
+ get
+ {
+ return new TheoryData>, string>
+ {
+ {
+ model => model.Property3["key"],
+ ""
+ },
+ {
+ model => model.Property4.Property5,
+ ""
+ },
+ {
+ model => model.Property4.Property6[0],
+ ""
+ }
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(TextAreaFor_UsesModelValueForComplexExpressionsData))]
+ public void TextAreaFor_ComplexExpressions_UsesModelValueForComplexExpressions(
+ Expression> expression,
+ string expected)
+ {
+ // Arrange
+ var model = new ComplexModel();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+ helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
+
+ helper.ViewData.Model.Property3["key"] = "Prop3Val";
+ helper.ViewData.Model.Property4.Property5 = "Prop5Val";
+ helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
+
+ // Act
+ var result = helper.TextAreaFor(expression);
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
+ }
+
+ public static TheoryData TextAreaFor_UsesModelStateValueForComplexExpressionsData
+ {
+ get
+ {
+ return new TheoryData>, string>
+ {
+ {
+ model => model.Property3["key"],
+ ""
+ },
+ {
+ model => model.Property4.Property5,
+ ""
+ },
+ {
+ model => model.Property4.Property6[0],
+ ""
+ }
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(TextAreaFor_UsesModelStateValueForComplexExpressionsData))]
+ public void TextAreaFor_ComplexExpressions_UsesModelStateValueForComplexExpressions(
+ Expression> expression,
+ string expected)
+ {
+ // Arrange
+ var model = new ComplexModel();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+ helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
+
+ helper.ViewData.ModelState.SetModelValue("pre.Property3[key]", "MProp3Val", "MProp3Val");
+ helper.ViewData.ModelState.SetModelValue("pre.Property4.Property5", "MProp5Val", "MProp5Val");
+ helper.ViewData.ModelState.SetModelValue("pre.Property4.Property6[0]", "MProp6Val", "MProp6Val");
+
+ helper.ViewData.Model.Property3["key"] = "Prop3Val";
+ helper.ViewData.Model.Property4.Property5 = "Prop5Val";
+ helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
+
+ // Act
+ var result = helper.TextAreaFor(expression);
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
+ }
+
+ public class ComplexModel
+ {
+ public string Property1 { get; set; }
+
+ public byte[] Bytes { get; set; }
+
+ [Required]
+ public string Property2 { get; set; }
+
+ public Dictionary Property3 { get; } = new Dictionary();
+
+ public NestedClass Property4 { get; } = new NestedClass();
+ }
+
+ public class NestedClass
+ {
+ public string Property5 { get; set; }
+
+ public List Property6 { get; } = new List();
+ }
+
private class TextAreaModelWithAPlaceholder
{
[Display(Prompt = "placeholder")]
diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextBoxTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextBoxTest.cs
index d2568dcbc1..e7dac3c03a 100644
--- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextBoxTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperTextBoxTest.cs
@@ -2,7 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc.TestCommon;
using Xunit;
@@ -58,6 +60,125 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
Assert.DoesNotContain(@"placeholder=""HtmlEncode[[placeholder]]""", result, StringComparison.Ordinal);
}
+ public static TheoryData TextBoxFor_UsesModelValueForComplexExpressionsData
+ {
+ get
+ {
+ return new TheoryData>, string>
+ {
+ {
+ model => model.Property3["key"],
+ @""
+ },
+ {
+ model => model.Property4.Property5,
+ @""
+ },
+ {
+ model => model.Property4.Property6[0],
+ @""
+ }
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(TextBoxFor_UsesModelValueForComplexExpressionsData))]
+ public void TextBoxFor_ComplexExpressions_UsesModelValueForComplexExpressions(
+ Expression> expression,
+ string expected)
+ {
+ // Arrange
+ var model = new ComplexModel();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+ helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
+
+ helper.ViewData.Model.Property3["key"] = "Prop3Val";
+ helper.ViewData.Model.Property4.Property5 = "Prop5Val";
+ helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
+
+ // Act
+ var result = helper.TextBoxFor(expression);
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
+ }
+
+ public static TheoryData TextBoxFor_UsesModelStateValueForComplexExpressionsData
+ {
+ get
+ {
+ return new TheoryData>, string>
+ {
+ {
+ model => model.Property3["key"],
+ @""
+ },
+ {
+ model => model.Property4.Property5,
+ @""
+ },
+ {
+ model => model.Property4.Property6[0],
+ @""
+ }
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(TextBoxFor_UsesModelStateValueForComplexExpressionsData))]
+ public void TextBoxFor_ComplexExpressions_UsesModelStateValueForComplexExpressions(
+ Expression> expression,
+ string expected)
+ {
+ // Arrange
+ var model = new ComplexModel();
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+ helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
+
+ helper.ViewData.ModelState.SetModelValue("pre.Property3[key]", "MProp3Val", "MProp3Val");
+ helper.ViewData.ModelState.SetModelValue("pre.Property4.Property5", "MProp5Val", "MProp5Val");
+ helper.ViewData.ModelState.SetModelValue("pre.Property4.Property6[0]", "MProp6Val", "MProp6Val");
+
+ helper.ViewData.Model.Property3["key"] = "Prop3Val";
+ helper.ViewData.Model.Property4.Property5 = "Prop5Val";
+ helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
+
+ // Act
+ var result = helper.TextBoxFor(expression);
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
+ }
+
+ public class ComplexModel
+ {
+ public string Property1 { get; set; }
+
+ public byte[] Bytes { get; set; }
+
+ [Required]
+ public string Property2 { get; set; }
+
+ public Dictionary Property3 { get; } = new Dictionary();
+
+ public NestedClass Property4 { get; } = new NestedClass();
+ }
+
+ public class NestedClass
+ {
+ public string Property5 { get; set; }
+
+ public List Property6 { get; } = new List();
+ }
+
private class TextBoxModel
{
[Display(Prompt = "placeholder")]
diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperValueExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperValueExtensionsTest.cs
new file mode 100644
index 0000000000..f1776922a9
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Rendering/HtmlHelperValueExtensionsTest.cs
@@ -0,0 +1,77 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.Rendering
+{
+ public class HtmlHelperValueExtensionsTest
+ {
+ [Fact]
+ public void Value_ReturnsModelValue()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+
+ // Act
+ var result = helper.Value("SomeProperty");
+
+ // Assert
+ Assert.Equal("ModelValue", result);
+ }
+
+ [Fact]
+ public void ValueFor_ReturnsModelValue()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+
+ // Act
+ var result = helper.ValueFor(m => m.SomeProperty);
+
+ // Assert
+ Assert.Equal("ModelValue", result);
+ }
+
+ [Fact]
+ public void ValueForModel_ReturnsModelValue()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+
+ // Act
+ var result = helper.ValueForModel();
+
+ // Assert
+ Assert.Equal("{ SomeProperty = ModelValue }", result);
+ }
+
+ [Fact]
+ public void ValueForModel_ReturnsModelValueWithSpecificFormat()
+ {
+ // Arrange
+ var model = new SomeModel { SomeProperty = "ModelValue" };
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+
+ // Act
+ var result = helper.ValueForModel(format: "-{0}-");
+
+ // Assert
+ Assert.Equal("-{ SomeProperty = ModelValue }-", result);
+ }
+
+ private class SomeModel
+ {
+ public string SomeProperty { get; set; }
+
+ public override string ToString()
+ {
+ return string.Format(
+ "{{ SomeProperty = {0} }}", SomeProperty ?? "(null)");
+ }
+ }
+ }
+}