diff --git a/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs b/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs index 1a54b54d0..0ff053c58 100644 --- a/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs +++ b/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.Linq; using System.Text; +using System.Web.Configuration; using System.Web.Mvc.Properties; using System.Web.Routing; using System.Web.UI.WebControls; @@ -18,6 +19,7 @@ namespace System.Web.Mvc.Html internal static class DefaultEditorTemplates { private const string HtmlAttributeKey = "htmlAttributes"; + private const string UsePasswordValue = "Switch.System.Web.Mvc.UsePasswordValue"; internal static string BooleanTemplate(HtmlHelper html) { @@ -149,11 +151,11 @@ internal static string HiddenInputTemplate(HtmlHelper html) MvcHtmlString hiddenResult; - if (htmlAttributesDict != null) + if (htmlAttributesDict != null) { hiddenResult = html.Hidden(String.Empty, model, htmlAttributesDict); - } - else + } + else { hiddenResult = html.Hidden(String.Empty, model, htmlAttributesObject); } @@ -178,9 +180,9 @@ private static IDictionary CreateHtmlAttributes(HtmlHelper html, { return MergeHtmlAttributes(htmlAttributesObject, className, inputType); } - + var htmlAttributes = new Dictionary() - { + { { "class", className } }; if (inputType != null) @@ -274,9 +276,21 @@ internal static string ObjectTemplate(HtmlHelper html, TemplateHelpers.TemplateH internal static string PasswordTemplate(HtmlHelper html) { - return html.Password(String.Empty, - html.ViewContext.ViewData.TemplateInfo.FormattedModelValue, - CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString(); + object value = null; + var usePasswordStrings = WebConfigurationManager.AppSettings.GetValues(UsePasswordValue); + bool usePasswordValue; + if (usePasswordStrings != null && + usePasswordStrings.Length > 0 && + bool.TryParse(usePasswordStrings[0], out usePasswordValue) && + usePasswordValue) + { + value = html.ViewContext.ViewData.TemplateInfo.FormattedModelValue; + } + + return html.Password( + name: String.Empty, + value: value, + htmlAttributes: CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString(); } private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo) diff --git a/test/System.Web.Mvc.Test/Html/Test/DefaultEditorTemplatesTest.cs b/test/System.Web.Mvc.Test/Html/Test/DefaultEditorTemplatesTest.cs index 74caa0430..4672bdcc7 100644 --- a/test/System.Web.Mvc.Test/Html/Test/DefaultEditorTemplatesTest.cs +++ b/test/System.Web.Mvc.Test/Html/Test/DefaultEditorTemplatesTest.cs @@ -731,14 +731,63 @@ public void ObjectTemplateDisplaysSimpleDisplayTextWithNonNullModelTemplateDepth public void PasswordTemplateTests() { Assert.Equal( - "", + "", DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper("Value"))); Assert.Equal( - "alert('XSS!')</script>\" />", + "", DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper(""))); } + [Fact] + public void PasswordTemplate_ReturnsInputElement_IgnoresValues() + { + // Arrange + var expected = ""; + + // Template ignores Model and FormattedModelValue. + var helper = MakeHtmlHelper(model: "Model string", formattedModelValue: "Formatted string"); + + var viewData = helper.ViewData; + var templateInfo = viewData.TemplateInfo; + templateInfo.HtmlFieldPrefix = "FieldPrefix"; + + // Template ignores ModelState and ViewData. + var valueProviderResult = new ValueProviderResult( + "Raw model string", + "Attempted model string", + CultureInfo.InvariantCulture); + viewData.ModelState.SetModelValue("FieldPrefix", valueProviderResult); + viewData["FieldPrefix"] = "ViewData string"; + + // Act + var result = DefaultEditorTemplates.PasswordTemplate(helper); + + // Assert + Assert.Equal(expected, result); + } + + [Fact] + public void PasswordTemplate_ReturnsInputElement_UsesHtmlAttributes() + { + // Arrange + var expected = ""; + var helper = MakeHtmlHelper(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, result); + } + public static TheoryDataSet PasswordTemplateHtmlAttributeData { get @@ -747,11 +796,11 @@ public static TheoryDataSet PasswordTemplateHtmlAttributeData { { new { @class = "form-control" }, - "" + "" }, { new { @class = "form-control", custom = "foo" }, - "" + "" } }; }