diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ValidationHelpers.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ValidationHelpers.cs index fec4837dde..97d45a2ba2 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ValidationHelpers.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ValidationHelpers.cs @@ -93,15 +93,17 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures Visit(indexEntry, metadata.ElementMetadata, orderedModelStateEntries); } } - - for (var i = 0; i < metadata.Properties.Count; i++) + else { - var propertyMetadata = metadata.Properties[i]; - var propertyModelStateEntry = modelStateEntry.GetModelStateForProperty(propertyMetadata.PropertyName); - if (propertyModelStateEntry != null) + for (var i = 0; i < metadata.Properties.Count; i++) { - Visit(propertyModelStateEntry, propertyMetadata, orderedModelStateEntries); - } + var propertyMetadata = metadata.Properties[i]; + var propertyModelStateEntry = modelStateEntry.GetModelStateForProperty(propertyMetadata.PropertyName); + if (propertyModelStateEntry != null) + { + Visit(propertyModelStateEntry, propertyMetadata, orderedModelStateEntries); + } + } } if (!modelStateEntry.IsContainerNode) diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs index 57730851cc..cba2243af4 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -587,6 +588,67 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers expectedMessage); } + [Fact] + public async Task ProcessAsync_GeneratesExpectedOutput_WithModelErrorForIEnumerable() + { + // Arrange + var expectedError = "Something went wrong."; + var expectedTagName = "not-div"; + var expectedAttributes = new TagHelperAttributeList + { + new TagHelperAttribute("class", "form-control validation-summary-errors"), + new TagHelperAttribute("data-valmsg-summary", "true"), + }; + + var metadataProvider = new TestModelMetadataProvider(); + var htmlGenerator = new TestableHtmlGenerator(metadataProvider); + var validationSummaryTagHelper = new ValidationSummaryTagHelper(htmlGenerator) + { + ValidationSummary = ValidationSummary.All, + }; + + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var tagHelperContext = new TagHelperContext( + tagName: "not-div", + allAttributes: new TagHelperAttributeList(), + items: new Dictionary(), + uniqueId: "test"); + var output = new TagHelperOutput( + expectedTagName, + attributes: new TagHelperAttributeList + { + { "class", "form-control" } + }, + getChildContentAsync: (useCachedResult, encoder) => + { + var tagHelperContent = new DefaultTagHelperContent(); + tagHelperContent.SetContent("Something"); + return Task.FromResult(tagHelperContent); + }); + output.PreContent.SetContent(expectedPreContent); + output.Content.SetContent(expectedContent); + output.PostContent.SetContent("Custom Content"); + + var model = new FormMetadata(); + var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); + validationSummaryTagHelper.ViewContext = viewContext; + + viewContext.ModelState.AddModelError(key: nameof(FormMetadata.ID), errorMessage: expectedError); + + // Act + await validationSummaryTagHelper.ProcessAsync(tagHelperContext, output); + + // Assert + Assert.Equal(expectedAttributes, output.Attributes, CaseSensitiveTagHelperAttributeComparer.Default); + Assert.Equal(expectedPreContent, output.PreContent.GetContent()); + Assert.Equal(expectedContent, output.Content.GetContent()); + Assert.Equal( + $"Custom Content", + output.PostContent.GetContent()); + Assert.Equal(expectedTagName, output.TagName); + } + private static ViewContext CreateViewContext() { var actionContext = new ActionContext( @@ -629,5 +691,22 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers // but no element does. public byte[] Empty { get; set; } } + + private class FormMetadata : IEnumerable + { + private List _fields = new List(); + + public int ID { get; set; } + + public IEnumerator GetEnumerator() + { + return _fields.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _fields.GetEnumerator(); + } + } } } \ No newline at end of file