Demonstrate #1485, #1487, #2662, #2664 in functional and unit tests

- test additional cases _close_ to these bugs as well

for #1485
- show odd `@Html.CheckBox()`, `@Html.Hidden()` behaviour in unit tests
- show odd `@Html.TextBox()` behaviour in functional tests (templates)

for #1487
- show odd `@Html.Value()` behaviour in unit tests
- show odd `@Html.RadioButton()`, `@Html.TextArea()` behaviour in functional tests
- show lack of validation attributes for `@Html.RadioButton()`, `<select>` tag helper

for #2662
- show odd `@Html.RadioButton(string.Empty)` behaviour in functional tests

for #2664
- show failures with `@Html.ListBox()` in unit tests

nits:
- test `IHtmlHelper` methods, not extensions
- use `ViewData`, not `ViewBag` in `HtmlGeneration_FormController`
- name test methods a bit more consistently
- rename `HtmlHelperValueExtensionsTest` to `HtmlHelperValueTest`
This commit is contained in:
Doug Bunting 2015-06-07 22:45:53 -07:00
parent 37d1881dad
commit afd5b4f2a6
10 changed files with 953 additions and 72 deletions

View File

@ -85,11 +85,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void CheckBoxCheckedWithOnlyName() public void CheckBoxCheckedWithOnlyName_GeneratesExpectedValue()
{ {
// Arrange // Arrange
var expected = var expected =
@"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " + @"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " +
@"data-val-required=""HtmlEncode[[The Boolean field is required.]]"" id=""HtmlEncode[[Property1]]"" " + @"data-val-required=""HtmlEncode[[The Boolean field is required.]]"" id=""HtmlEncode[[Property1]]"" " +
@"name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" " + @"name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" " +
@"value=""HtmlEncode[[true]]"" /><input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />"; @"value=""HtmlEncode[[true]]"" /><input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
@ -121,6 +121,170 @@ namespace Microsoft.AspNet.Mvc.Rendering
Assert.Equal(expected, html.ToString()); Assert.Equal(expected, html.ToString());
} }
[Fact]
public void CheckBoxNotInTemplate_GetsValueFromViewDataDictionary()
{
// Arrange
var expected =
@"<input checked=""HtmlEncode[[checked]]"" id=""HtmlEncode[[Property1]]"" " +
@"name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData());
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.Model = new TestModel();
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void CheckBoxInTemplate_GetsValueFromViewDataDictionary()
{
// Arrange
var expected =
@"<input checked=""HtmlEncode[[checked]]"" id=""HtmlEncode[[Prefix_Property1]]"" " +
@"name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData());
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.Remove(nameof(TestModel.Property1));
helper.ViewData["Prefix.Property1"] = true;
helper.ViewData.Model = new TestModel();
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void CheckBoxNotInTemplate_GetsValueFromPropertyOfViewDataEntry()
{
// Arrange
var expected =
@"<input checked=""HtmlEncode[[checked]]"" id=""HtmlEncode[[Prefix_Property1]]"" " +
@"name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData());
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.Remove(nameof(TestModel.Property1));
helper.ViewData["Prefix"] = new TestModel { Property1 = true };
helper.ViewData.Model = new TestModel();
// Act
var html = helper.CheckBox("Prefix.Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void CheckBoxInTemplate_GetsValueFromPropertyOfViewDataEntry()
{
// Arrange
var expected =
@"<input checked=""HtmlEncode[[checked]]"" id=""HtmlEncode[[Prefix_Property1]]"" " +
@"name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData());
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.Remove(nameof(TestModel.Property1));
helper.ViewData["Prefix"] = new TestModel { Property1 = true };
helper.ViewData.Model = new TestModel();
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void CheckBoxNotInTemplate_GetsModelValue_IfModelStateAndViewDataEmpty()
{
// Arrange
var expected =
@"<input checked=""HtmlEncode[[checked]]"" id=""HtmlEncode[[Property1]]"" " +
@"name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var metadataProvider = new EmptyModelMetadataProvider();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(new ViewDataDictionary<TestModel>(metadataProvider));
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.Model = new TestModel { Property1 = true };
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact(Skip = "#1485, unable to get Model value.")]
public void CheckBoxInTemplate_GetsModelValue_IfModelStateAndViewDataEmpty()
{
// Arrange
var expected =
@"<input checked=""HtmlEncode[[checked]]"" id=""HtmlEncode[[Prefix_Property1]]"" " +
@"name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var metadataProvider = new EmptyModelMetadataProvider();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(new ViewDataDictionary<TestModel>(metadataProvider));
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.Model = new TestModel { Property1 = true };
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void CheckBoxNotInTemplate_NotChecked_IfPropertyIsNotFound()
{
// Arrange
var expected =
@"<input id=""HtmlEncode[[Property1]]"" " +
@"name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var metadataProvider = new EmptyModelMetadataProvider();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(new ViewDataDictionary<TestModel>(metadataProvider));
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void CheckBoxInTemplate_NotChecked_IfPropertyIsNotFound()
{
// Arrange
var expected =
@"<input id=""HtmlEncode[[Prefix_Property1]]"" " +
@"name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Prefix.Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var metadataProvider = new EmptyModelMetadataProvider();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(new ViewDataDictionary<TestModel>(metadataProvider));
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact] [Fact]
public void CheckBoxGeneratesUnobtrusiveValidationAttributes() public void CheckBoxGeneratesUnobtrusiveValidationAttributes()
{ {
@ -142,9 +306,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
{ {
// Arrange // Arrange
var expected = var expected =
@"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " + @"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " +
@"data-val-required=""HtmlEncode[[The Boolean field is required.]]"" id=""HtmlEncode[[Property1]]"" " + @"data-val-required=""HtmlEncode[[The Boolean field is required.]]"" id=""HtmlEncode[[Property1]]"" " +
@"name=""HtmlEncode[[Property1]]"" Property1-Property3=""HtmlEncode[[Property3ObjValue]]"" " + @"name=""HtmlEncode[[Property1]]"" Property1-Property3=""HtmlEncode[[Property3ObjValue]]"" " +
@"type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" /><input " + @"type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" /><input " +
@"name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />"; @"name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData()); var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData());
@ -158,7 +322,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void CheckBoxWithPrefix_ReplaceDotsInIdByDefaultWithUnderscores() public void CheckBoxInTemplate_ReplaceDotsInIdByDefaultWithUnderscores()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix_Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" " + var expected = @"<input id=""HtmlEncode[[MyPrefix_Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" " +
@ -176,7 +340,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void CheckBoxWithPrefix_ReplacesDotsInIdWithIdDotReplacement() public void CheckBoxInTemplate_ReplacesDotsInIdWithIdDotReplacement()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix!!!Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" " + var expected = @"<input id=""HtmlEncode[[MyPrefix!!!Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" " +
@ -196,7 +360,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void CheckBoxWithPrefixAndEmptyName() public void CheckBoxInTemplate_WithEmptyExpression_GeneratesExpectedValue()
{ {
// Arrange // Arrange
var expected = var expected =
@ -219,7 +383,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void CheckBoxWithComplexExpressionsEvaluatesValuesInViewDataDictionary() public void CheckBoxWithComplexExpressionsEvaluatesValuesInViewDataDictionary()
{ {
// Arrange // Arrange
var expected = var expected =
@"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " + @"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " +
@"data-val-required=""HtmlEncode[[The Boolean field is required.]]"" id=""HtmlEncode[[ComplexProperty_Property1]]"" " + @"data-val-required=""HtmlEncode[[The Boolean field is required.]]"" id=""HtmlEncode[[ComplexProperty_Property1]]"" " +
@"name=""HtmlEncode[[ComplexProperty." + @"name=""HtmlEncode[[ComplexProperty." +
@ -248,7 +412,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
viewData.ModelState.SetModelValue("Property1", valueProviderResult); viewData.ModelState.SetModelValue("Property1", valueProviderResult);
// Act // Act
var html = helper.CheckBoxFor(m => m.Property1); var html = helper.CheckBoxFor(m => m.Property1, htmlAttributes: null);
// Assert // Assert
Assert.Equal(expected, html.ToString()); Assert.Equal(expected, html.ToString());
@ -275,7 +439,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
// Act // Act
var html = helper.CheckBoxFor(m => m.Property1); var html = helper.CheckBoxFor(m => m.Property1, htmlAttributes: null);
// Assert // Assert
Assert.Equal(expected, html.ToString()); Assert.Equal(expected, html.ToString());
@ -286,7 +450,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
{ {
// Arrange // Arrange
var expected = var expected =
@"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " + @"<input checked=""HtmlEncode[[checked]]"" data-val=""HtmlEncode[[true]]"" " +
@"data-val-required=""HtmlEncode[[The Property3 field is required.]]"" " + @"data-val-required=""HtmlEncode[[The Property3 field is required.]]"" " +
@"id=""HtmlEncode[[Property3]]"" name=""HtmlEncode[[Property3]]"" type=""HtmlEncode[[checkbox]]"" " + @"id=""HtmlEncode[[Property3]]"" name=""HtmlEncode[[Property3]]"" type=""HtmlEncode[[checkbox]]"" " +
@"value=""HtmlEncode[[false]]"" /><input name=""HtmlEncode[[Property3]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />"; @"value=""HtmlEncode[[false]]"" /><input name=""HtmlEncode[[Property3]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
@ -326,7 +490,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void CheckBoxFor_UsesModelStateAttemptedValue(string attemptedValue, string expectedChecked) public void CheckBoxFor_UsesModelStateAttemptedValue(string attemptedValue, string expectedChecked)
{ {
// Arrange // Arrange
var expected = var expected =
@"<input {0}data-val=""HtmlEncode[[true]]"" data-val-required=""HtmlEncode[[The Property1 field is required.]]"" " + @"<input {0}data-val=""HtmlEncode[[true]]"" data-val-required=""HtmlEncode[[The Property1 field is required.]]"" " +
@"id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" + @"id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />"; @"<input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />";
@ -339,7 +503,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
viewData.ModelState.SetModelValue("Property1", valueProviderResult); viewData.ModelState.SetModelValue("Property1", valueProviderResult);
// Act // Act
var html = helper.CheckBoxFor(m => m.Property1); var html = helper.CheckBoxFor(m => m.Property1, htmlAttributes: null);
// Assert // Assert
Assert.Equal(expected, html.ToString()); Assert.Equal(expected, html.ToString());
@ -365,10 +529,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void CheckBoxForWith_AttributeDictionary_GeneratesExpectedAttributes() public void CheckBoxFor_WithAttributeDictionary_GeneratesExpectedAttributes()
{ {
// Arrange // Arrange
var expected = var expected =
@"<input data-val=""HtmlEncode[[true]]"" data-val-required=""HtmlEncode[[The Property1 field is required.]]"" " + @"<input data-val=""HtmlEncode[[true]]"" data-val-required=""HtmlEncode[[The Property1 field is required.]]"" " +
@"id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" " + @"id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" " +
@"Property3=""HtmlEncode[[Property3Value]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" /><input " + @"Property3=""HtmlEncode[[Property3Value]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" /><input " +
@ -384,7 +548,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void CheckBoxForWithPrefix() public void CheckBoxForInTemplate_GeneratesExpectedValue()
{ {
// Arrange // Arrange
var expected = var expected =
@ -407,7 +571,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void CheckBoxFor_WithComplexExpressions_DoesNotUseValuesFromViewDataDictionary() public void CheckBoxFor_WithComplexExpressions_DoesNotUseValuesFromViewDataDictionary()
{ {
// Arrange // Arrange
var expected = var expected =
@"<input data-val=""HtmlEncode[[true]]"" data-val-required=""HtmlEncode[[The Property1 field is required.]]"" " + @"<input data-val=""HtmlEncode[[true]]"" data-val-required=""HtmlEncode[[The Property1 field is required.]]"" " +
@"id=""HtmlEncode[[ComplexProperty_Property1]]"" name=""HtmlEncode[[ComplexProperty." + @"id=""HtmlEncode[[ComplexProperty_Property1]]"" name=""HtmlEncode[[ComplexProperty." +
@"Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" /><input name=""HtmlEncode[[ComplexProperty.Property1]]"" " + @"Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" /><input name=""HtmlEncode[[ComplexProperty.Property1]]"" " +

View File

@ -59,6 +59,76 @@ namespace Microsoft.AspNet.Mvc.Rendering
Assert.Equal(expected, result.ToString()); Assert.Equal(expected, result.ToString());
} }
[Fact]
public void HiddenNotInTemplate_GetsValueFromPropertyOfViewDataEntry()
{
// Arrange
var expected = @"<input id=""HtmlEncode[[Prefix_Property1]]"" name=""HtmlEncode[[Prefix.Property1]]"" " +
@"type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[contained-view-data-value]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.Model.Property1 = "model-property1-value";
helper.ViewData["Prefix"] = new HiddenModel { Property1 = "contained-view-data-value" };
// Act
var html = helper.Hidden("Prefix.Property1", value: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void HiddenInTemplate_GetsValueFromPropertyOfViewDataEntry()
{
// Arrange
var expected = @"<input id=""HtmlEncode[[Prefix_Property1]]"" name=""HtmlEncode[[Prefix.Property1]]"" " +
@"type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[contained-view-data-value]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
helper.ViewData.Model.Property1 = "model-property1-value";
helper.ViewData["Prefix"] = new HiddenModel { Property1 = "contained-view-data-value" };
// Act
var html = helper.Hidden("Property1", value: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void HiddenNotInTemplate_GetsValueFromViewDataEntry_EvenIfNull()
{
// Arrange
var expected = @"<input id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" " +
@"type=""HtmlEncode[[hidden]]"" value="""" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.Model.Property1 = "model-property1-value";
helper.ViewData["Property1"] = null;
// Act
var html = helper.Hidden("Property1", value: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void HiddenInTemplate_GetsValueFromViewDataEntry_EvenIfNull()
{
// Arrange
var expected = @"<input id=""HtmlEncode[[Prefix_Property1]]"" name=""HtmlEncode[[Prefix.Property1]]"" " +
@"type=""HtmlEncode[[hidden]]"" value="""" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
helper.ViewData.Model.Property1 = "model-property1-value";
helper.ViewData["Prefix.Property1"] = null;
// Act
var html = helper.Hidden("Property1", value: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact] [Fact]
public void HiddenOverridesValueFromAttributesWithArgumentValue() public void HiddenOverridesValueFromAttributesWithArgumentValue()
{ {
@ -92,7 +162,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void HiddenWithNullValueAndNullModel_GeneratesExpectedValue() public void HiddenWithNonNullValue_GeneratesExpectedValue()
{ {
// Arrange // Arrange
var expected = @"<input data-key=""HtmlEncode[[value]]"" id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" " + var expected = @"<input data-key=""HtmlEncode[[value]]"" id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" " +
@ -155,13 +225,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void HiddenUsesPropertyValue_IfModelStateAndViewDataDoNotHavePropertyAndExplicitValueIsNull() public void HiddenNotInTemplate_GetsModelValue_IfModelStateAndViewDataEmpty()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[property-value]]"" />"; var expected = @"<input id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[property-value]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.ModelState.Clear();
helper.ViewData.Clear();
helper.ViewData.Model.Property1 = "property-value"; helper.ViewData.Model.Property1 = "property-value";
// Act // Act
@ -171,15 +239,29 @@ namespace Microsoft.AspNet.Mvc.Rendering
Assert.Equal(expected, result.ToString()); Assert.Equal(expected, result.ToString());
} }
[Fact(Skip = "#1485, unable to get Model value.")]
public void HiddenInTemplate_GetsModelValue_IfModelStateAndViewDataEmpty()
{
// Arrange
var expected = @"<input id=""HtmlEncode[[Prefix_Property1]]"" name=""HtmlEncode[[Prefix.Property1]]"" " +
@"type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[property-value]]"" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
helper.ViewData.Model.Property1 = "property-value";
// Act
var html = helper.Hidden("Property1", value: null, htmlAttributes: new { value = "attribute-value" });
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact] [Fact]
public void HiddenDoesNotUsesAttributeValue() public void HiddenNotInTemplate_DoesNotUseAttributeValue()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value="""" />"; var expected = @"<input id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value="""" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.ModelState.Clear();
helper.ViewData.Clear();
helper.ViewData.Model.Property1 = null;
// Act // Act
var result = helper.Hidden("Property1", value: null, htmlAttributes: new { value = "attribute-value" }); var result = helper.Hidden("Property1", value: null, htmlAttributes: new { value = "attribute-value" });
@ -189,7 +271,23 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void HiddenReturnsEmptyValue_IfPropertyIsNotFound() public void HiddenInTemplate_DoesNotUseAttributeValue()
{
// Arrange
var expected = @"<input id=""HtmlEncode[[Prefix_Property1]]"" name=""HtmlEncode[[Prefix.Property1]]"" " +
@"type=""HtmlEncode[[hidden]]"" value="""" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithNonNullModel());
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.Hidden("Property1", value: null, htmlAttributes: new { value = "attribute-value" });
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void HiddenNotInTemplate_GetsEmptyValue_IfPropertyIsNotFound()
{ {
// Arrange // Arrange
var expected = @"<input baz=""HtmlEncode[[BazValue]]"" id=""HtmlEncode[[keyNotFound]]"" name=""HtmlEncode[[keyNotFound]]"" type=""HtmlEncode[[hidden]]"" " + var expected = @"<input baz=""HtmlEncode[[BazValue]]"" id=""HtmlEncode[[keyNotFound]]"" name=""HtmlEncode[[keyNotFound]]"" type=""HtmlEncode[[hidden]]"" " +
@ -205,7 +303,23 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void HiddenWithPrefix_GeneratesExpectedValue() public void HiddenInTemplate_GetsEmptyValue_IfPropertyIsNotFound()
{
// Arrange
var expected = @"<input id=""HtmlEncode[[Prefix_keyNotFound]]"" name=""HtmlEncode[[Prefix.keyNotFound]]"" " +
@"type=""HtmlEncode[[hidden]]"" value="""" />";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues());
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.Hidden("keyNotFound", value: null, htmlAttributes: null);
// Assert
Assert.Equal(expected, html.ToString());
}
[Fact]
public void HiddenInTemplate_WithExplicitValue_GeneratesExpectedValue()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix_Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " + var expected = @"<input id=""HtmlEncode[[MyPrefix_Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " +
@ -221,7 +335,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void HiddenWithPrefixAndEmptyName_GeneratesExpectedValue() public void HiddenInTemplate_WithExplicitValueAndEmptyName_GeneratesExpectedValue()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix]]"" name=""HtmlEncode[[MyPrefix]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[fooValue]]"" />"; var expected = @"<input id=""HtmlEncode[[MyPrefix]]"" name=""HtmlEncode[[MyPrefix]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[fooValue]]"" />";
@ -236,7 +350,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void HiddenUsesPrefixName_ToLookupPropertyValueInModelState() public void HiddenInTemplate_UsesPrefixName_ToLookupPropertyValueInModelState()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix$Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " + var expected = @"<input id=""HtmlEncode[[MyPrefix$Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " +
@ -258,7 +372,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
[Fact] [Fact]
public void HiddenUsesPrefixName_ToLookupPropertyValueInViewData() public void HiddenInTemplate_UsesPrefixNameToLookupPropertyValueInViewData()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix$Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " + var expected = @"<input id=""HtmlEncode[[MyPrefix$Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " +
@ -509,7 +623,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
// This test ensures that specifying a the prefix does not affect the expression result. // This test ensures that specifying a the prefix does not affect the expression result.
[Fact] [Fact]
public void HiddenForWithPrefix_GeneratesExpectedValue() public void HiddenForInTemplate_GeneratesExpectedValue()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix_Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " + var expected = @"<input id=""HtmlEncode[[MyPrefix_Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " +
@ -519,14 +633,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";
// Act // Act
var result = helper.HiddenFor(m => m.Property1); var result = helper.HiddenFor(m => m.Property1, htmlAttributes: null);
// Assert // Assert
Assert.Equal(expected, result.ToString()); Assert.Equal(expected, result.ToString());
} }
[Fact] [Fact]
public void HiddenForWithPrefix_UsesPrefixWhenLookingUpModelStateValues() public void HiddenForInTemplate_UsesPrefixWhenLookingUpModelStateValues()
{ {
// Arrange // Arrange
var expected = @"<input id=""HtmlEncode[[MyPrefix$Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " + var expected = @"<input id=""HtmlEncode[[MyPrefix$Property1]]"" name=""HtmlEncode[[MyPrefix.Property1]]"" type=""HtmlEncode[[hidden]]"" " +
@ -542,7 +656,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
helper.ViewData.ModelState.Add("MyPrefix$Property1", GetModelState("modelstate-with-iddotreplacement")); helper.ViewData.ModelState.Add("MyPrefix$Property1", GetModelState("modelstate-with-iddotreplacement"));
// Act // Act
var result = helper.HiddenFor(m => m.Property1); var result = helper.HiddenFor(m => m.Property1, htmlAttributes: null);
// Assert // Assert
Assert.Equal(expected, result.ToString()); Assert.Equal(expected, result.ToString());
@ -671,7 +785,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
[Theory] [Theory]
[MemberData(nameof(HiddenFor_UsesModelStateValueForComplexExpressionsData))] [MemberData(nameof(HiddenFor_UsesModelStateValueForComplexExpressionsData))]
public void HiddenFor_UsesModelStateValueForComplexExpressions( public void HiddenForInTemplate_UsesModelStateValueForComplexExpressions(
Expression<Func<HiddenModel, string>> expression, Expression<Func<HiddenModel, string>> expression,
string expected) string expected)
{ {
@ -718,13 +832,20 @@ namespace Microsoft.AspNet.Mvc.Rendering
}; };
} }
private static ViewDataDictionary<HiddenModel> GetViewDataWithModelStateAndModelAndViewDataValues() private static ViewDataDictionary<HiddenModel> GetViewDataWithNonNullModel()
{ {
var viewData = new ViewDataDictionary<HiddenModel>(new EmptyModelMetadataProvider()) var viewData = new ViewDataDictionary<HiddenModel>(new EmptyModelMetadataProvider())
{ {
Model = new HiddenModel(), Model = new HiddenModel(),
["Property1"] = "view-data-val",
}; };
return viewData;
}
private static ViewDataDictionary<HiddenModel> GetViewDataWithModelStateAndModelAndViewDataValues()
{
var viewData = GetViewDataWithNonNullModel();
viewData["Property1"] = "view-data-val";
viewData.ModelState.Add("Property1", GetModelState("ModelStateValue")); viewData.ModelState.Add("Property1", GetModelState("ModelStateValue"));
return viewData; return viewData;

View File

@ -59,6 +59,17 @@ namespace Microsoft.AspNet.Mvc.Rendering
new SelectListItem { Group = DisabledGroup, Selected = true, Text = "Two", Value = "2"}, new SelectListItem { Group = DisabledGroup, Selected = true, Text = "Two", Value = "2"},
new SelectListItem { Group = DisabledGroup, Selected = true, Text = "Three", Value = "3"}, new SelectListItem { Group = DisabledGroup, Selected = true, Text = "Three", Value = "3"},
}; };
private static readonly List<SelectListItem> SourcesSelectList = new List<SelectListItem>
{
new SelectListItem { Text = SelectSources.ModelStateEntry.ToString() },
new SelectListItem { Text = SelectSources.ModelStateEntryWithPrefix.ToString() },
new SelectListItem { Text = SelectSources.ViewDataEntry.ToString() },
new SelectListItem { Text = SelectSources.PropertyOfViewDataEntry.ToString() },
new SelectListItem { Text = SelectSources.ViewDataEntryWithPrefix.ToString() },
new SelectListItem { Text = SelectSources.PropertyOfViewDataEntryWithPrefix.ToString() },
new SelectListItem { Text = SelectSources.ModelValue.ToString() },
new SelectListItem { Text = SelectSources.PropertyOfModel.ToString() },
};
// Select list -> expected HTML with null model, expected HTML with model containing "2". // Select list -> expected HTML with null model, expected HTML with model containing "2".
public static TheoryData<IEnumerable<SelectListItem>, string, string> DropDownListDataSet public static TheoryData<IEnumerable<SelectListItem>, string, string> DropDownListDataSet
@ -371,6 +382,200 @@ namespace Microsoft.AspNet.Mvc.Rendering
Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected));
} }
[Fact]
public void DropDownListNotInTemplate_GetsModelStateEntry()
{
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.ModelStateEntry, allowMultiple: false);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingSources>(provider, modelState)
{
["Property1"] = SelectSources.ViewDataEntry,
["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix,
["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry },
};
viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact]
public void DropDownListInTemplate_GetsModelStateEntry()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(
SelectSources.ModelStateEntryWithPrefix,
allowMultiple: false);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingSources>(provider, modelState)
{
["Property1"] = SelectSources.ViewDataEntry,
["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix,
["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry },
};
viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel };
viewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact]
public void DropDownListNotInTemplate_GetsViewDataEntry_IfModelStateEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.ViewDataEntry, allowMultiple: false);
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingSources>(provider)
{
["Property1"] = SelectSources.ViewDataEntry,
["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix,
["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry },
};
viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact(Skip = "#1487, incorrectly matches Property1 entry (without prefix) in ViewData.")]
public void DropDownListInTemplate_GetsViewDataEntry_IfModelStateEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(
SelectSources.ViewDataEntryWithPrefix,
allowMultiple: false);
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingSources>(provider)
{
["Property1"] = SelectSources.ViewDataEntry,
["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix,
["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry },
};
viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel };
viewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact(Skip = "#1487, incorrectly matches Property1 entry (without prefix) in ViewData.")]
public void DropDownListInTemplate_GetsPropertyOfViewDataEntry_IfModelStateEmptyAndNoViewDataEntryWithPrefix()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(
SelectSources.PropertyOfViewDataEntry,
allowMultiple: false);
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingSources>(provider)
{
["Property1"] = SelectSources.ViewDataEntry,
["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry },
};
viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel };
viewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact]
public void DropDownListNotInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.PropertyOfModel, allowMultiple: false);
var model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact]
public void DropDownListInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(SelectSources.PropertyOfModel, allowMultiple: false);
var model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Theory] [Theory]
[MemberData(nameof(DropDownListDataSet))] [MemberData(nameof(DropDownListDataSet))]
public void DropDownListFor_WithNullModel_GeneratesExpectedValue( public void DropDownListFor_WithNullModel_GeneratesExpectedValue(
@ -588,6 +793,200 @@ namespace Microsoft.AspNet.Mvc.Rendering
Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected));
} }
[Fact]
public void ListBoxNotInTemplate_GetsModelStateEntry()
{
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.ModelStateEntry, allowMultiple: true);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingListOfSources>(provider, modelState)
{
["Property1"] = new[] { SelectSources.ViewDataEntry },
["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix },
["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } },
};
viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact]
public void ListBoxInTemplate_GetsModelStateEntry()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(
SelectSources.ModelStateEntryWithPrefix,
allowMultiple: true);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingListOfSources>(provider, modelState)
{
["Property1"] = new[] { SelectSources.ViewDataEntry },
["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix },
["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } },
};
viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } };
viewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact(Skip = "#2664, throws ArgumentNullException")]
public void ListBoxNotInTemplate_GetsViewDataEntry_IfModelStateEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.ViewDataEntry, allowMultiple: true);
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingListOfSources>(provider)
{
["Property1"] = new[] { SelectSources.ViewDataEntry },
["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix },
["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } },
};
viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact(Skip = "#2664, throws ArgumentNullException")]
public void ListBoxInTemplate_GetsViewDataEntry_IfModelStateEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(
SelectSources.ViewDataEntryWithPrefix,
allowMultiple: true);
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingListOfSources>(provider)
{
["Property1"] = new[] { SelectSources.ViewDataEntry },
["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix },
["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } },
};
viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } };
viewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact(Skip = "#2664, throws ArgumentNullException")]
public void ListBoxInTemplate_GetsPropertyOfViewDataEntry_IfModelStateEmptyAndNoViewDataEntryWithPrefix()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(
SelectSources.PropertyOfViewDataEntry,
allowMultiple: true);
var provider = TestModelMetadataProvider.CreateDefaultProvider();
var viewData = new ViewDataDictionary<ModelContainingListOfSources>(provider)
{
["Property1"] = new[] { SelectSources.ViewDataEntry },
["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } },
};
viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } };
viewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact(Skip = "#2664, throws ArgumentNullException")]
public void ListBoxNotInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.PropertyOfModel, allowMultiple: true);
var model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewContext.ClientValidationEnabled = false;
// Act
var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Fact(Skip = "#2664, throws ArgumentNullException")]
public void ListBoxInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty()
{
// Arrange
var expectedHtml = GetExpectedSelectElementWithPrefix(SelectSources.PropertyOfModel, allowMultiple: true);
var model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewContext.ClientValidationEnabled = false;
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null);
// Assert
Assert.Equal(expectedHtml, html.ToString());
}
[Theory] [Theory]
[MemberData(nameof(ListBoxDataSet))] [MemberData(nameof(ListBoxDataSet))]
public void ListBoxFor_WithNullModel_GeneratesExpectedValue( public void ListBoxFor_WithNullModel_GeneratesExpectedValue(
@ -1072,6 +1471,51 @@ namespace Microsoft.AspNet.Mvc.Rendering
VerifySelectList(expected, result); VerifySelectList(expected, result);
} }
private static string GetExpectedSelectElement(SelectSources source, bool allowMultiple)
{
return $"<select id=\"HtmlEncode[[Property1]]\"{ GetMultiple(allowMultiple) } " +
"name=\"HtmlEncode[[Property1]]\">" +
$"{ GetOption(SelectSources.ModelStateEntry, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ModelStateEntryWithPrefix, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ViewDataEntry, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.PropertyOfViewDataEntry, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ViewDataEntryWithPrefix, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.PropertyOfViewDataEntryWithPrefix, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ModelValue, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.PropertyOfModel, source) }{ Environment.NewLine }" +
"</select>";
}
private static string GetExpectedSelectElementWithPrefix(SelectSources source, bool allowMultiple)
{
return $"<select id=\"HtmlEncode[[Prefix_Property1]]\"{ GetMultiple(allowMultiple) } " +
"name=\"HtmlEncode[[Prefix.Property1]]\">" +
$"{ GetOption(SelectSources.ModelStateEntry, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ModelStateEntryWithPrefix, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ViewDataEntry, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.PropertyOfViewDataEntry, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ViewDataEntryWithPrefix, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.PropertyOfViewDataEntryWithPrefix, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.ModelValue, source) }{ Environment.NewLine }" +
$"{ GetOption(SelectSources.PropertyOfModel, source) }{ Environment.NewLine }" +
"</select>";
}
private static string GetMultiple(bool allowMultiple)
{
return allowMultiple ? " multiple=\"HtmlEncode[[multiple]]\"" : string.Empty;
}
private static string GetOption(SelectSources optionSource, SelectSources source)
{
return $"<option{ GetSelected(optionSource, source) }>HtmlEncode[[{ optionSource.ToString() }]]</option>";
}
private static string GetSelected(SelectSources optionSource, SelectSources source)
{
return optionSource == source ? " selected=\"HtmlEncode[[selected]]\"" : string.Empty;
}
// Confirm methods that wrap GetEnumSelectList(ModelMetadata) are not changing anything in returned collection. // Confirm methods that wrap GetEnumSelectList(ModelMetadata) are not changing anything in returned collection.
private void VerifySelectList(IEnumerable<SelectListItem> expected, IEnumerable<SelectListItem> actual) private void VerifySelectList(IEnumerable<SelectListItem> expected, IEnumerable<SelectListItem> actual)
{ {
@ -1137,6 +1581,28 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
} }
private enum SelectSources
{
ModelStateEntry,
ModelStateEntryWithPrefix,
ViewDataEntry,
PropertyOfViewDataEntry,
ViewDataEntryWithPrefix,
PropertyOfViewDataEntryWithPrefix,
ModelValue,
PropertyOfModel,
};
private class ModelContainingSources
{
public SelectSources Property1 { get; set; }
}
private class ModelContainingListOfSources
{
public List<SelectSources> Property1 { get; } = new List<SelectSources>();
}
private class ClassWithFields private class ClassWithFields
{ {
public const int Zero = 0; public const int Zero = 0;

View File

@ -11,25 +11,127 @@ using Xunit;
namespace Microsoft.AspNet.Mvc.Core namespace Microsoft.AspNet.Mvc.Core
{ {
/// <summary> /// <summary>
/// Test the <see cref="HtmlHelperValueExtensions" /> class. /// Test the <see cref="IHtmlHelper.Value" /> and <see cref="IHtmlHelper{TModel}.ValueFor"/> methods.
/// </summary> /// </summary>
public class HtmlHelperValueExtensionsTest public class HtmlHelperValueTest
{ {
// Value // Value
[Fact] [Fact]
public void ValueGetsValueFromViewData() public void ValueNotInTemplate_GetsValueFromViewData()
{ {
// Arrange // Arrange
var helper = GetHtmlHelper(); var helper = GetHtmlHelper();
// Act // Act
var html = helper.Value("StringProperty"); var html = helper.Value("StringProperty", format: null);
// Assert // Assert
Assert.Equal("ViewDataValue", html); Assert.Equal("ViewDataValue", html);
} }
[Fact(Skip = "$1487, finds 'StringProperty' entry (without prefix) instead.")]
public void ValueInTemplate_GetsValueFromPrefixedViewDataEntry()
{
// Arrange
var helper = GetHtmlHelper();
helper.ViewData["Prefix.StringProperty"] = "PrefixedViewDataValue";
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.Value("StringProperty", format: null);
// Assert
Assert.Equal("PrefixedViewDataValue", html);
}
[Fact]
public void ValueNotInTemplate_GetsValueFromPropertyOfViewDataEntry()
{
// Arrange
var helper = GetHtmlHelper();
helper.ViewData["Prefix"] = new { StringProperty = "ContainedViewDataValue" };
// Act
var html = helper.Value("Prefix.StringProperty", format: null);
// Assert
Assert.Equal("ContainedViewDataValue", html);
}
[Fact(Skip = "$1487, finds 'StringProperty' entry (without prefix) instead.")]
public void ValueInTemplate_GetsValueFromPropertyOfViewDataEntry()
{
// Arrange
var helper = GetHtmlHelper();
helper.ViewData["Prefix"] = new { StringProperty = "ContainedViewDataValue" };
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.Value("StringProperty", format: null);
// Assert
Assert.Equal("ContainedViewDataValue", html);
}
[Fact]
public void ValueNotInTemplate_GetsValueFromModel_IfNoViewDataEntry()
{
// Arrange
var helper = GetHtmlHelper();
helper.ViewData.Clear();
// Act
var html = helper.Value("StringProperty", format: null);
// Assert
Assert.Equal("ModelStringPropertyValue", html);
}
[Fact]
public void ValueInTemplate_GetsValueFromModel_IfNoViewDataEntry()
{
// Arrange
var helper = GetHtmlHelper();
helper.ViewData.Clear();
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.Value("StringProperty", format: null);
// Assert
Assert.Equal("ModelStringPropertyValue", html);
}
[Fact]
public void ValueNotInTemplate_GetsValueFromViewData_EvenIfNull()
{
// Arrange
var helper = GetHtmlHelper();
helper.ViewData["StringProperty"] = null;
// Act
var html = helper.Value("StringProperty", format: null);
// Assert
Assert.Empty(html);
}
[Fact(Skip = "$1487, finds 'StringProperty' entry (without prefix) instead.")]
public void ValueInTemplate_GetsValueFromViewData_EvenIfNull()
{
// Arrange
var helper = GetHtmlHelper();
helper.ViewData["Prefix.StringProperty"] = null;
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix";
// Act
var html = helper.Value("StringProperty", format: null);
// Assert
Assert.Empty(html);
}
// ValueFor // ValueFor
[Fact] [Fact]
@ -39,7 +141,7 @@ namespace Microsoft.AspNet.Mvc.Core
var helper = GetHtmlHelper(); var helper = GetHtmlHelper();
// Act // Act
var html = helper.ValueFor(m => m.StringProperty); var html = helper.ValueFor(m => m.StringProperty, format: null);
// Assert // Assert
Assert.Equal("ModelStringPropertyValue", html); Assert.Equal("ModelStringPropertyValue", html);
@ -76,9 +178,9 @@ namespace Microsoft.AspNet.Mvc.Core
viewData.ModelState["FieldPrefix"] = modelState; viewData.ModelState["FieldPrefix"] = modelState;
// Act & Assert // Act & Assert
Assert.Equal("StringPropertyRawValue", helper.Value("StringProperty")); Assert.Equal("StringPropertyRawValue", helper.Value("StringProperty", format: null));
Assert.Equal("StringPropertyRawValue", helper.ValueFor(m => m.StringProperty)); Assert.Equal("StringPropertyRawValue", helper.ValueFor(m => m.StringProperty, format: null));
Assert.Equal("ModelRawValue", helper.ValueForModel()); Assert.Equal("ModelRawValue", helper.ValueForModel(format: null));
} }
[Fact] [Fact]
@ -91,10 +193,10 @@ namespace Microsoft.AspNet.Mvc.Core
"{ StringProperty = ModelStringPropertyValue, ObjectProperty = 01/01/1900 00:00:00 }"; "{ StringProperty = ModelStringPropertyValue, ObjectProperty = 01/01/1900 00:00:00 }";
// Act & Assert // Act & Assert
Assert.Equal(expectedModelValue, helper.Value(expression: string.Empty)); Assert.Equal(expectedModelValue, helper.Value(expression: string.Empty, format: null));
Assert.Equal(expectedModelValue, helper.Value(expression: null)); // null is another alias for current model Assert.Equal(expectedModelValue, helper.Value(expression: null, format: null)); // null is another alias for current model
Assert.Equal(expectedModelValue, helper.ValueFor(m => m)); Assert.Equal(expectedModelValue, helper.ValueFor(m => m, format: null));
Assert.Equal(expectedModelValue, helper.ValueForModel()); Assert.Equal(expectedModelValue, helper.ValueForModel(format: null));
} }
[Fact] [Fact]
@ -135,7 +237,7 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ValueForModel("<{0}>")); helper.ValueForModel("<{0}>"));
Assert.Equal("<ViewDataValue <\"\">>", helper.Value("StringProperty", "<{0}>")); Assert.Equal("<ViewDataValue <\"\">>", helper.Value("StringProperty", "<{0}>"));
Assert.Equal("<ModelStringPropertyValue <\"\">>", helper.ValueFor(m => m.StringProperty, "<{0}>")); Assert.Equal("<ModelStringPropertyValue <\"\">>", helper.ValueFor(m => m.StringProperty, "<{0}>"));
Assert.Equal("ObjectPropertyRawValue <\"\">", helper.ValueFor(m => m.ObjectProperty)); Assert.Equal("ObjectPropertyRawValue <\"\">", helper.ValueFor(m => m.ObjectProperty, format: null));
} }
private sealed class TestModel private sealed class TestModel

View File

@ -3,13 +3,15 @@
<form action="/HtmlGeneration_Home/EmployeeList" method="post"> <form action="/HtmlGeneration_Home/EmployeeList" method="post">
<div> <div>
<label for="z0__Number">Number</label> <label for="z0__Number">Number</label>
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" data-val-required="The Number field is required." disabled="disabled" id="z0__Number" name="[0].Number" readonly="readonly" type="text" value="0" />
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" data-val-required="The Number field is required." disabled="disabled" id="z0__Number" name="[0].Number" readonly="readonly" type="text" value="" />
<input class="form-control" type="number" id="z0__Number" name="[0].Number" value="0" /> <input class="form-control" type="number" id="z0__Number" name="[0].Number" value="0" />
</div> </div>
<div> <div>
<label class="employee" for="z0__Name">Name</label> <label class="employee" for="z0__Name">Name</label>
<textarea id="z0__Name" name="[0].Name"> <textarea id="z0__Name" name="[0].Name">
EmployeeName_0</textarea> Name value that should not be seen.</textarea>
</div> </div>
<div> <div>
<label class="employee" for="z0__PhoneNumber">PhoneNumber</label> <label class="employee" for="z0__PhoneNumber">PhoneNumber</label>
@ -18,7 +20,10 @@ EmployeeName_0</textarea>
<div> <div>
<label class="employee" for="z0__Gender">Gender</label> <label class="employee" for="z0__Gender">Gender</label>
<select data-val="true" data-val-required="The Gender field is required." id="z0__Gender" name="[0].Gender"><option selected="selected">Male</option>
<input disabled="disabled" id="z0__Gender" name="[0].Gender" readonly="readonly" type="radio" value="Female" />
<select id="z0__Gender" name="[0].Gender"><option selected="selected">Male</option>
<option>Female</option> <option>Female</option>
</select> </select>
</div> </div>
@ -35,13 +40,15 @@ EmployeeName_0</textarea>
</div> </div>
<div> <div>
<label for="z1__Number">Number</label> <label for="z1__Number">Number</label>
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" data-val-required="The Number field is required." disabled="disabled" id="z1__Number" name="[1].Number" readonly="readonly" type="text" value="1" />
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" data-val-required="The Number field is required." disabled="disabled" id="z1__Number" name="[1].Number" readonly="readonly" type="text" value="" />
<input class="form-control" type="number" id="z1__Number" name="[1].Number" value="1" /> <input class="form-control" type="number" id="z1__Number" name="[1].Number" value="1" />
</div> </div>
<div> <div>
<label class="employee" for="z1__Name">Name</label> <label class="employee" for="z1__Name">Name</label>
<textarea id="z1__Name" name="[1].Name"> <textarea id="z1__Name" name="[1].Name">
EmployeeName_1</textarea> Name value that should not be seen.</textarea>
</div> </div>
<div> <div>
<label class="employee" for="z1__PhoneNumber">PhoneNumber</label> <label class="employee" for="z1__PhoneNumber">PhoneNumber</label>
@ -50,7 +57,10 @@ EmployeeName_1</textarea>
<div> <div>
<label class="employee" for="z1__Gender">Gender</label> <label class="employee" for="z1__Gender">Gender</label>
<select data-val="true" data-val-required="The Gender field is required." id="z1__Gender" name="[1].Gender"><option>Male</option>
<input disabled="disabled" id="z1__Gender" name="[1].Gender" readonly="readonly" type="radio" value="Female" />
<select id="z1__Gender" name="[1].Gender"><option>Male</option>
<option selected="selected">Female</option> <option selected="selected">Female</option>
</select> </select>
</div> </div>
@ -67,13 +77,15 @@ EmployeeName_1</textarea>
</div> </div>
<div> <div>
<label for="z2__Number">Number</label> <label for="z2__Number">Number</label>
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" data-val-required="The Number field is required." disabled="disabled" id="z2__Number" name="[2].Number" readonly="readonly" type="text" value="2" />
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" data-val-required="The Number field is required." disabled="disabled" id="z2__Number" name="[2].Number" readonly="readonly" type="text" value="" />
<input class="form-control" type="number" id="z2__Number" name="[2].Number" value="2" /> <input class="form-control" type="number" id="z2__Number" name="[2].Number" value="2" />
</div> </div>
<div> <div>
<label class="employee" for="z2__Name">Name</label> <label class="employee" for="z2__Name">Name</label>
<textarea id="z2__Name" name="[2].Name"> <textarea id="z2__Name" name="[2].Name">
EmployeeName_2</textarea> Name value that should not be seen.</textarea>
</div> </div>
<div> <div>
<label class="employee" for="z2__PhoneNumber">PhoneNumber</label> <label class="employee" for="z2__PhoneNumber">PhoneNumber</label>
@ -82,7 +94,10 @@ EmployeeName_2</textarea>
<div> <div>
<label class="employee" for="z2__Gender">Gender</label> <label class="employee" for="z2__Gender">Gender</label>
<select data-val="true" data-val-required="The Gender field is required." id="z2__Gender" name="[2].Gender"><option selected="selected">Male</option>
<input disabled="disabled" id="z2__Gender" name="[2].Gender" readonly="readonly" type="radio" value="Female" />
<select id="z2__Gender" name="[2].Gender"><option selected="selected">Male</option>
<option>Female</option> <option>Female</option>
</select> </select>
</div> </div>

View File

@ -1,4 +1,4 @@
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title></title> <title></title>
@ -69,7 +69,8 @@
<div> <div>
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_Gender]]">HtmlEncode[[Gender]]</label> <label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_Gender]]">HtmlEncode[[Gender]]</label>
<input data-val="HtmlEncode[[true]]" data-val-required="HtmlEncode[[The Gender field is required.]]" id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Male]]" /> Male <input data-val="HtmlEncode[[true]]" data-val-required="HtmlEncode[[The Gender field is required.]]" id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Male]]" /> Male
<input checked="HtmlEncode[[checked]]" id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Female]]" /> Female
<input id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Female]]" /> Female
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Gender]]" data-valmsg-replace="HtmlEncode[[true]]"></span> <span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Gender]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
</div> </div>
<div class="HtmlEncode[[validation-summary-valid order]]" data-valmsg-summary="HtmlEncode[[true]]"><ul><li style="display:none"></li> <div class="HtmlEncode[[validation-summary-valid order]]" data-valmsg-summary="HtmlEncode[[true]]"><ul><li style="display:none"></li>

View File

@ -1,4 +1,4 @@
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title></title> <title></title>
@ -69,7 +69,8 @@
<div> <div>
<label class="order" for="Customer_Gender">Gender</label> <label class="order" for="Customer_Gender">Gender</label>
<input data-val="true" data-val-required="The Gender field is required." id="Customer_Gender" name="Customer.Gender" type="radio" value="Male" /> Male <input data-val="true" data-val-required="The Gender field is required." id="Customer_Gender" name="Customer.Gender" type="radio" value="Male" /> Male
<input checked="checked" id="Customer_Gender" name="Customer.Gender" type="radio" value="Female" /> Female
<input id="Customer_Gender" name="Customer.Gender" type="radio" value="Female" /> Female
<span class="field-validation-valid" data-valmsg-for="Customer.Gender" data-valmsg-replace="true"></span> <span class="field-validation-valid" data-valmsg-for="Customer.Gender" data-valmsg-replace="true"></span>
</div> </div>
<div class="validation-summary-valid order" data-valmsg-summary="true"><ul><li style="display:none"></li> <div class="validation-summary-valid order" data-valmsg-summary="true"><ul><li style="display:none"></li>

View File

@ -56,14 +56,14 @@ namespace HtmlGenerationWebSite.Controllers
public IActionResult Order() public IActionResult Order()
{ {
ViewBag.Items = _productsListWithSelection; ViewData["Items"] = _productsListWithSelection;
return View(_order); return View(_order);
} }
public IActionResult OrderUsingHtmlHelpers() public IActionResult OrderUsingHtmlHelpers()
{ {
ViewBag.Items = _productsListWithSelection; ViewData["Items"] = _productsListWithSelection;
return View(_order); return View(_order);
} }
@ -124,12 +124,17 @@ namespace HtmlGenerationWebSite.Controllers
}, },
}; };
// Extra data that should be ignored within a template. But #1487 currently affects RadioButton and
// TextArea as well as ModelMetadata for <select> tag helper.
ViewData[nameof(Employee.Gender)] = "Gender value that will not match.";
ViewData[nameof(Employee.Name)] = "Name value that should not be seen.";
return View(employees); return View(employees);
} }
public IActionResult CreateWarehouse() public IActionResult CreateWarehouse()
{ {
ViewBag.Items = _productsList; ViewData["Items"] = _productsList;
return View(); return View();
} }

View File

@ -4,12 +4,14 @@
<div> <div>
@Html.LabelFor(m => m.Number) @Html.LabelFor(m => m.Number)
@Html.TextBoxFor(m => m.Number, htmlAttributes: new { disabled = "disabled", @readonly= "readonly" }) @* Due to #1485, text box will be empty though all employees have Number values. *@
@Html.TextBox(nameof(Model.Number), value: null, htmlAttributes: new { disabled = "disabled", @readonly = "readonly" })
<input asp-for="Number" type="number" class="form-control" /> <input asp-for="Number" type="number" class="form-control" />
</div> </div>
<div> <div>
<label asp-for="Name" class="employee"></label> <label asp-for="Name" class="employee"></label>
@Html.TextAreaFor(m => m.Name) @* Due to #1487, text area will contain incorrect "Value that should not be seen." *@
@Html.TextArea(nameof(Model.Name))
</div> </div>
<div> <div>
<label asp-for="PhoneNumber" class="employee"></label> <label asp-for="PhoneNumber" class="employee"></label>
@ -20,11 +22,14 @@
var genders = new SelectList(new string[] { "Male", "Female" }); var genders = new SelectList(new string[] { "Male", "Female" });
} }
<label asp-for="Gender" class="employee"></label> <label asp-for="Gender" class="employee"></label>
@* Due to #1487, radio button will not be checked. Employee is Female but incorrect information does not match. *@
@Html.RadioButton(nameof(Model.Gender), "Female", htmlAttributes: new { disabled = "disabled", @readonly = "readonly" })
@* Due to #1487, <select> tag helper will not generate expected validation attributes. *@
<select asp-for="Gender" asp-items="genders"></select> <select asp-for="Gender" asp-items="genders"></select>
</div> </div>
<div> <div>
<label asp-for="Remote" class="employee"></label> <label asp-for="Remote" class="employee"></label>
@Html.CheckBoxFor(m=>m.Remote) @Html.CheckBoxFor(m => m.Remote)
</div> </div>
<div> <div>
<label asp-for="OfficeNumber" class="employee"></label> <label asp-for="OfficeNumber" class="employee"></label>

View File

@ -1,4 +1,5 @@
@using HtmlGenerationWebSite.Models @using HtmlGenerationWebSite.Models
@model Gender @model Gender
@Html.RadioButtonFor(m => m, value: "Male") Male @Html.RadioButtonFor(m => m, value: "Male") Male
@Html.RadioButtonFor(m => m, value: "Female") Female @* Due to #2662 radio button will not be checked because help ignores this expression." *@
@Html.RadioButton(expression: string.Empty, value: "Female") Female