diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs
index 09c2c60e97..408448c651 100644
--- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs
+++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs
@@ -20,6 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
public static class DefaultEditorTemplates
{
private const string HtmlAttributeKey = "htmlAttributes";
+ private const string UsePasswordValue = "Switch.Microsoft.AspNetCore.Mvc.UsePasswordValue";
public static IHtmlContent BooleanTemplate(IHtmlHelper htmlHelper)
{
@@ -312,9 +313,15 @@ public static IHtmlContent ObjectTemplate(IHtmlHelper htmlHelper)
public static IHtmlContent PasswordTemplate(IHtmlHelper htmlHelper)
{
+ object value = null;
+ if (AppContext.TryGetSwitch(UsePasswordValue, out var usePasswordValue) && usePasswordValue)
+ {
+ value = htmlHelper.ViewData.TemplateInfo.FormattedModelValue;
+ }
+
return htmlHelper.Password(
expression: null,
- value: htmlHelper.ViewData.TemplateInfo.FormattedModelValue,
+ value: value,
htmlAttributes: CreateHtmlAttributes(htmlHelper, "text-box single-line password"));
}
diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs
index e7e1b568bc..793f7a176e 100644
--- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs
@@ -521,6 +521,55 @@ public void MultilineTextTemplate_ReturnsTextArea()
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
}
+ [Fact]
+ public void PasswordTemplate_ReturnsInputElement_IgnoresValues()
+ {
+ // Arrange
+ var expected = "";
+
+ // Template ignores Model.
+ var model = "Model string";
+
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
+ var viewData = helper.ViewData;
+ var templateInfo = viewData.TemplateInfo;
+ templateInfo.HtmlFieldPrefix = "FieldPrefix";
+
+ // Template ignores FormattedModelValue, ModelState and ViewData.
+ templateInfo.FormattedModelValue = "Formatted string";
+ viewData.ModelState.SetModelValue("FieldPrefix", "Raw model string", "Attempted model string");
+ viewData["FieldPrefix"] = "ViewData string";
+
+ // Act
+ var result = DefaultEditorTemplates.PasswordTemplate(helper);
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
+ }
+
+ [Fact]
+ public void PasswordTemplate_ReturnsInputElement_UsesHtmlAttributes()
+ {
+ // Arrange
+ var expected = "";
+ var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: null);
+ var viewData = helper.ViewData;
+ var templateInfo = viewData.TemplateInfo;
+ templateInfo.HtmlFieldPrefix = "FieldPrefix";
+
+ viewData["htmlAttributes"] = new { @class = "super", value = "Html attributes string" };
+
+ // Act
+ var result = DefaultEditorTemplates.PasswordTemplate(helper);
+
+ // Assert
+ Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
+ }
+
[Theory]
[MemberData(nameof(TemplateNameData))]
public void Editor_CallsExpectedHtmlHelper(string templateName, string expectedResult)