Conversation
📝 WalkthroughWalkthroughAdds an opt-in FlattenCollectionItems option for XML serialization, implements flattened enumerable conversion paths, updates default converter encapsulation logic, provides an IServiceCollection.AddMinimalXmlOptions extension, and adds tests and assets covering flattened/non-flattened serialization and DI registration. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant XmlSerializerOptions as XmlSerializerOptions\n(FlattenCollectionItems)
participant XmlFormatterOptions as XmlFormatterOptions\n(RefreshWithConverterDependencies)
participant XmlConverterDecorator as XmlConverterDecorator\n(AddEnumerableConverter)
participant DefaultXmlConverter as DefaultXmlConverter\n(WriteXmlChildrenEncapsulated)
participant XmlWriter as XmlWriter
Client->>XmlSerializerOptions: set FlattenCollectionItems = true
Client->>XmlFormatterOptions: RefreshWithConverterDependencies()
XmlFormatterOptions->>XmlFormatterOptions: detect Settings.FlattenCollectionItems
alt flattenItems enabled
XmlFormatterOptions->>XmlConverterDecorator: AddEnumerableConverter(flattenItems: true)
XmlConverterDecorator->>XmlConverterDecorator: configure flattened emission (repeat root-named elements)
else flattenItems disabled
XmlFormatterOptions->>XmlConverterDecorator: AddEnumerableConverter(flattenItems: false)
XmlConverterDecorator->>XmlConverterDecorator: configure Item-wrapped emission
end
Client->>DefaultXmlConverter: Serialize collection property
DefaultXmlConverter->>DefaultXmlConverter: decide encapsulation (skip if dedicated converter)
alt Flattened mode
DefaultXmlConverter->>XmlWriter: emit repeated root-named elements
else Non-flattened mode
DefaultXmlConverter->>XmlWriter: emit `Item` wrapper elements
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs (1)
105-153:⚠️ Potential issue | 🔴 CriticalFlattening top-level sequences can produce invalid XML documents.
At Line 105, top-level non-list/non-dictionary enumerables get
q = "Enumerable". Then withflattenItems = true, Lines 139-151 emit repeated<Enumerable>elements without a single document root. This can fail with writer-state/document-root errors.Suggested fix
- if (flattenItems && q != null) + var canFlattenItems = flattenItems && q != null && w.WriteState != WriteState.Start; + if (canFlattenItems) { if (isDictionaryLike) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs` around lines 105 - 153, The code sets q = new XmlQualifiedEntity("Enumerable") for top-level enumerables then with flattenItems==true writes repeated elements (using q.LocalName) without a single document root, causing invalid XML; fix by ensuring a single container element is written when the XmlWriter is at Start: when flattenItems && q != null && w.WriteState == WriteState.Start, call w.WriteStartElement(q.LocalName) once before iterating the sequence and w.WriteEndElement() after the loop (both for the dictionary-like and non-dictionary branches) so repeated item elements are wrapped in a single root rather than emitting bare sibling elements.
🧹 Nitpick comments (6)
src/Cuemon.Extensions.AspNetCore.Xml/ServiceCollectionExtensions.cs (1)
6-28: Switch this new file to file-scoped namespace style.Implementation is good, but namespace style should match the repo rule for new files.
As per coding guidelines
**/*.cs: Use file-scoped namespaces (namespace Cuemon.Foo;) for new .cs files.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Cuemon.Extensions.AspNetCore.Xml/ServiceCollectionExtensions.cs` around lines 6 - 28, Update this file to use a file-scoped namespace instead of the block namespace: replace the current block namespace declaration wrapping the ServiceCollectionExtensions class with a file-scoped namespace declaration for Cuemon.Extensions.AspNetCore.Xml; ensure the class ServiceCollectionExtensions and its AddMinimalXmlOptions method (which calls Validator.ThrowIfNull and returns services.AddXmlExceptionResponseFormatter(setup)) remain unchanged other than the namespace syntax swap so the file conforms to the repo rule for new .cs files.test/Cuemon.Xml.Tests/Assets/WorldNode.cs (1)
3-29: Use file-scoped namespace in this new file.This new file uses a block-scoped namespace; repo rules require file-scoped namespaces for new
.csfiles.As per coding guidelines
**/*.cs: Use file-scoped namespaces (namespace Cuemon.Foo;) for new .cs files.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/Cuemon.Xml.Tests/Assets/WorldNode.cs` around lines 3 - 29, This file uses a block-scoped namespace; change it to a file-scoped namespace declaration (namespace Cuemon.Xml.Assets;) at the top of the file, then remove the enclosing braces so the classes WorldNode, WorldLinks, and Link remain under that file-scoped namespace; ensure no other code structure is altered and that using directives (if any) remain above the file-scoped namespace.test/Cuemon.Xml.Tests/Assets/RegionStats.cs (1)
3-11: Please use file-scoped namespace for this new asset file.The new file currently uses block-scoped namespace syntax.
As per coding guidelines
**/*.cs: Use file-scoped namespaces (namespace Cuemon.Foo;) for new .cs files.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/Cuemon.Xml.Tests/Assets/RegionStats.cs` around lines 3 - 11, The file uses a block-scoped namespace; change it to a file-scoped namespace declaration for the RegionStats asset by replacing the current "namespace Cuemon.Xml.Assets { ... }" block with a single-line file-scoped namespace "namespace Cuemon.Xml.Assets;" and keep the public class RegionStats (and its properties Name and Indicators) at top-level in the file; ensure no extra braces remain and the using directives (if any) remain above the file-scoped namespace.test/Cuemon.Extensions.AspNetCore.Tests/Xml/ServiceCollectionExtensionsTest.cs (1)
11-72: Convert this new test file to file-scoped namespace syntax.Test logic and structure look good; only the namespace declaration style is off from repo rules for new files.
As per coding guidelines
**/*.cs: Use file-scoped namespaces (namespace Cuemon.Foo;) for new .cs files.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/Cuemon.Extensions.AspNetCore.Tests/Xml/ServiceCollectionExtensionsTest.cs` around lines 11 - 72, The file uses a block namespace declaration; convert it to file-scoped namespace syntax by changing "namespace Cuemon.Extensions.AspNetCore.Xml { ... }" to "namespace Cuemon.Extensions.AspNetCore.Xml;" and moving the class ServiceCollectionExtensionsTest (and its contents) out of the braces so the file uses the file-scoped namespace form; ensure the class signature, constructor, and test methods (e.g., AddMinimalXmlOptions_ShouldThrowArgumentNullException_WhenServicesIsNull, AddMinimalXmlOptions_ShouldRegisterXmlFormatterOptions, AddMinimalXmlOptions_ShouldAlsoRegisterXmlExceptionResponseFormatter, AddMinimalXmlOptions_ShouldOnlyRegisterXmlExceptionResponseFormatterOnce_WhenCalledMultipleTimes) remain unchanged.test/Cuemon.Xml.Tests/Serialization/Formatters/XmlFormatterTest.cs (1)
111-171: Consider extracting repeated test fixtures into helpers.
WorldNodeandRegionStatssetup is repeated across tests. Moving them to private factory methods would cut duplication and simplify future updates.Also applies to: 203-240
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/Cuemon.Xml.Tests/Serialization/Formatters/XmlFormatterTest.cs` around lines 111 - 171, Tests repeat constructing WorldNode and RegionStats fixtures; extract these into private factory/helper methods (e.g., CreateWorldNode() and CreateRegionStats()) used by tests like Serialize_ShouldProduce_PascalCase_Structure_ForWorldNode and other test methods around lines referenced. Move the repeated initialization of WorldNode (including Links and Children) and RegionStats into those helpers, return fully populated objects, and update tests to call the helpers to reduce duplication and make future changes easier; ensure helper methods are private within the XmlFormatterTest class and preserve existing property values and list contents.src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs (1)
113-134: Extract shared dictionary serialization path to reduce drift.The key/value reflection and type-resolution logic is duplicated in both flatten and non-flatten branches. A small helper would reduce maintenance risk and keep behavior consistent.
Also applies to: 159-181
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs` around lines 113 - 134, The dictionary element serialization logic (used when isDictionaryLike in the current method and again in the other branch around the 159-181 region) duplicates reflection and type-resolution steps (keyProperty/valueProperty retrieval, keyValue/valueValue extraction, valuePropertyType normalization, keyName sanitization and the conditional Decorator.Enclose(w).WriteObject vs w.WriteElementString write path). Extract these steps into a single private helper (e.g., SerializeDictionaryElement or WriteDictionaryEntry) that accepts the XmlWriter, the element object, the Decorator and any options/context needed, performs the Key/Value reflection and valuePropertyType resolution (including the typeof(object) -> actual type fallback), builds the sanitized keyName, and performs the correct complex vs simple write using Decorator.Enclose(w).WriteObject or w.WriteElementString; then replace both the flatten and non-flatten blocks to call this helper so behavior is consistent and maintenance risk is reduced.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In
`@src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs`:
- Around line 105-153: The code sets q = new XmlQualifiedEntity("Enumerable")
for top-level enumerables then with flattenItems==true writes repeated elements
(using q.LocalName) without a single document root, causing invalid XML; fix by
ensuring a single container element is written when the XmlWriter is at Start:
when flattenItems && q != null && w.WriteState == WriteState.Start, call
w.WriteStartElement(q.LocalName) once before iterating the sequence and
w.WriteEndElement() after the loop (both for the dictionary-like and
non-dictionary branches) so repeated item elements are wrapped in a single root
rather than emitting bare sibling elements.
---
Nitpick comments:
In `@src/Cuemon.Extensions.AspNetCore.Xml/ServiceCollectionExtensions.cs`:
- Around line 6-28: Update this file to use a file-scoped namespace instead of
the block namespace: replace the current block namespace declaration wrapping
the ServiceCollectionExtensions class with a file-scoped namespace declaration
for Cuemon.Extensions.AspNetCore.Xml; ensure the class
ServiceCollectionExtensions and its AddMinimalXmlOptions method (which calls
Validator.ThrowIfNull and returns
services.AddXmlExceptionResponseFormatter(setup)) remain unchanged other than
the namespace syntax swap so the file conforms to the repo rule for new .cs
files.
In
`@src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs`:
- Around line 113-134: The dictionary element serialization logic (used when
isDictionaryLike in the current method and again in the other branch around the
159-181 region) duplicates reflection and type-resolution steps
(keyProperty/valueProperty retrieval, keyValue/valueValue extraction,
valuePropertyType normalization, keyName sanitization and the conditional
Decorator.Enclose(w).WriteObject vs w.WriteElementString write path). Extract
these steps into a single private helper (e.g., SerializeDictionaryElement or
WriteDictionaryEntry) that accepts the XmlWriter, the element object, the
Decorator and any options/context needed, performs the Key/Value reflection and
valuePropertyType resolution (including the typeof(object) -> actual type
fallback), builds the sanitized keyName, and performs the correct complex vs
simple write using Decorator.Enclose(w).WriteObject or w.WriteElementString;
then replace both the flatten and non-flatten blocks to call this helper so
behavior is consistent and maintenance risk is reduced.
In
`@test/Cuemon.Extensions.AspNetCore.Tests/Xml/ServiceCollectionExtensionsTest.cs`:
- Around line 11-72: The file uses a block namespace declaration; convert it to
file-scoped namespace syntax by changing "namespace
Cuemon.Extensions.AspNetCore.Xml { ... }" to "namespace
Cuemon.Extensions.AspNetCore.Xml;" and moving the class
ServiceCollectionExtensionsTest (and its contents) out of the braces so the file
uses the file-scoped namespace form; ensure the class signature, constructor,
and test methods (e.g.,
AddMinimalXmlOptions_ShouldThrowArgumentNullException_WhenServicesIsNull,
AddMinimalXmlOptions_ShouldRegisterXmlFormatterOptions,
AddMinimalXmlOptions_ShouldAlsoRegisterXmlExceptionResponseFormatter,
AddMinimalXmlOptions_ShouldOnlyRegisterXmlExceptionResponseFormatterOnce_WhenCalledMultipleTimes)
remain unchanged.
In `@test/Cuemon.Xml.Tests/Assets/RegionStats.cs`:
- Around line 3-11: The file uses a block-scoped namespace; change it to a
file-scoped namespace declaration for the RegionStats asset by replacing the
current "namespace Cuemon.Xml.Assets { ... }" block with a single-line
file-scoped namespace "namespace Cuemon.Xml.Assets;" and keep the public class
RegionStats (and its properties Name and Indicators) at top-level in the file;
ensure no extra braces remain and the using directives (if any) remain above the
file-scoped namespace.
In `@test/Cuemon.Xml.Tests/Assets/WorldNode.cs`:
- Around line 3-29: This file uses a block-scoped namespace; change it to a
file-scoped namespace declaration (namespace Cuemon.Xml.Assets;) at the top of
the file, then remove the enclosing braces so the classes WorldNode, WorldLinks,
and Link remain under that file-scoped namespace; ensure no other code structure
is altered and that using directives (if any) remain above the file-scoped
namespace.
In `@test/Cuemon.Xml.Tests/Serialization/Formatters/XmlFormatterTest.cs`:
- Around line 111-171: Tests repeat constructing WorldNode and RegionStats
fixtures; extract these into private factory/helper methods (e.g.,
CreateWorldNode() and CreateRegionStats()) used by tests like
Serialize_ShouldProduce_PascalCase_Structure_ForWorldNode and other test methods
around lines referenced. Move the repeated initialization of WorldNode
(including Links and Children) and RegionStats into those helpers, return fully
populated objects, and update tests to call the helpers to reduce duplication
and make future changes easier; ensure helper methods are private within the
XmlFormatterTest class and preserve existing property values and list contents.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/Cuemon.Extensions.AspNetCore.Xml/ServiceCollectionExtensions.cssrc/Cuemon.Extensions.Xml/Serialization/Converters/XmlConverterExtensions.cssrc/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cssrc/Cuemon.Xml/Serialization/Converters/DefaultXmlConverter.cssrc/Cuemon.Xml/Serialization/Formatters/XmlFormatterOptions.cssrc/Cuemon.Xml/Serialization/XmlSerializerOptions.cstest/Cuemon.Extensions.AspNetCore.Tests/Xml/ServiceCollectionExtensionsTest.cstest/Cuemon.Xml.Tests/Assets/RegionStats.cstest/Cuemon.Xml.Tests/Assets/WorldNode.cstest/Cuemon.Xml.Tests/Serialization/Formatters/XmlFormatterTest.cs
There was a problem hiding this comment.
Pull request overview
This PR extends Cuemon’s XML serialization to support “flattened” collection output (avoiding generic <Item> wrappers), and adds ASP.NET Core DI helpers/tests to simplify registering XML formatter services for minimal API scenarios.
Changes:
- Added
FlattenCollectionItemstoXmlSerializerOptionsand wired it intoXmlFormatterOptionsto swap in a flattened enumerable converter. - Updated enumerable converter logic and
DefaultXmlConverterencapsulation to avoid duplicate element wrapping. - Added new XML serialization test assets and new tests (including DI registration tests for
AddMinimalXmlOptions).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/Cuemon.Xml.Tests/Serialization/Formatters/XmlFormatterTest.cs | Adds tests covering world hierarchy and flattened dictionary/list XML output. |
| test/Cuemon.Xml.Tests/Assets/WorldNode.cs | Adds asset types used for XML serialization test coverage. |
| test/Cuemon.Xml.Tests/Assets/RegionStats.cs | Adds asset type for dictionary serialization test coverage. |
| test/Cuemon.Extensions.AspNetCore.Tests/Xml/ServiceCollectionExtensionsTest.cs | Adds tests for AddMinimalXmlOptions DI registration and idempotency. |
| src/Cuemon.Xml/Serialization/XmlSerializerOptions.cs | Introduces FlattenCollectionItems option. |
| src/Cuemon.Xml/Serialization/Formatters/XmlFormatterOptions.cs | Applies FlattenCollectionItems by replacing/adding enumerable converter. |
| src/Cuemon.Xml/Serialization/Converters/DefaultXmlConverter.cs | Avoids double-wrapping elements when a dedicated converter exists. |
| src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs | Adds flattenItems support to enumerable converter implementation. |
| src/Cuemon.Extensions.Xml/Serialization/Converters/XmlConverterExtensions.cs | Exposes flattenItems on list-based extension overload. |
| src/Cuemon.Extensions.AspNetCore.Xml/ServiceCollectionExtensions.cs | Adds AddMinimalXmlOptions extension for minimal API scenarios. |
| var keyName = Decorator.Enclose(keyValue.ToString()).SanitizeXmlElementName(); | ||
| if (Decorator.Enclose(valuePropertyType).IsComplex()) | ||
| { | ||
| Decorator.Enclose(writer).WriteObject(valueValue, valuePropertyType); | ||
| Decorator.Enclose(w).WriteObject(valueValue, valuePropertyType, opts => opts.Settings.RootName = new XmlQualifiedEntity(keyName)); | ||
| } | ||
| else | ||
| { | ||
| writer.WriteValue(valueValue); | ||
| w.WriteElementString(keyName, Convert.ToString(valueValue, CultureInfo.InvariantCulture)); | ||
| } | ||
| writer.WriteEndElement(); | ||
| } | ||
| w.WriteEndElement(); | ||
| } | ||
| else | ||
| { | ||
| foreach (var item in sequence) | ||
| foreach (var item in o) | ||
| { | ||
| if (item == null) { continue; } | ||
| var itemType = item.GetType(); | ||
| writer.WriteStartElement("Item"); | ||
| if (Decorator.Enclose(itemType).IsComplex()) | ||
| { | ||
| Decorator.Enclose(writer).WriteObject(item, itemType); | ||
| var localName = q.LocalName; | ||
| Decorator.Enclose(w).WriteObject(item, itemType, opts => opts.Settings.RootName = new XmlQualifiedEntity(localName)); | ||
| } | ||
| else | ||
| { | ||
| writer.WriteValue(item); | ||
| w.WriteElementString(q.LocalName, Convert.ToString(item, CultureInfo.InvariantCulture)); | ||
| } | ||
| writer.WriteEndElement(); | ||
| } |
There was a problem hiding this comment.
In the flattenItems path, primitive values are emitted via Convert.ToString(..., InvariantCulture) and WriteElementString, which changes formatting vs the rest of the XML stack (e.g., bool becomes True/False instead of lowercase, DateTime may lose round-trip formatting). Consider using the same value formatting approach as DefaultXmlConverter (eg. Wrapper.ParseInstance(...) / XML-safe formatting) to keep output stable and schema-friendly.
| @@ -118,38 +122,84 @@ public static IDecorator<IList<XmlConverter>> AddEnumerableConverter(this IDecor | |||
| var valueValue = valueProperty.GetValue(element, null); | |||
| var valuePropertyType = valueProperty.PropertyType; | |||
| if (valuePropertyType == typeof(object) && valueValue != null) { valuePropertyType = valueValue.GetType(); } | |||
| writer.WriteStartElement("Item"); | |||
| writer.WriteAttributeString("name", keyValue.ToString()); | |||
| var keyName = Decorator.Enclose(keyValue.ToString()).SanitizeXmlElementName(); | |||
| if (Decorator.Enclose(valuePropertyType).IsComplex()) | |||
| { | |||
| Decorator.Enclose(writer).WriteObject(valueValue, valuePropertyType); | |||
| Decorator.Enclose(w).WriteObject(valueValue, valuePropertyType, opts => opts.Settings.RootName = new XmlQualifiedEntity(keyName)); | |||
| } | |||
| else | |||
| { | |||
| writer.WriteValue(valueValue); | |||
| w.WriteElementString(keyName, Convert.ToString(valueValue, CultureInfo.InvariantCulture)); | |||
| } | |||
| writer.WriteEndElement(); | |||
| } | |||
| w.WriteEndElement(); | |||
| } | |||
| else | |||
| { | |||
| foreach (var item in sequence) | |||
| foreach (var item in o) | |||
| { | |||
| if (item == null) { continue; } | |||
| var itemType = item.GetType(); | |||
| writer.WriteStartElement("Item"); | |||
| if (Decorator.Enclose(itemType).IsComplex()) | |||
| { | |||
| Decorator.Enclose(writer).WriteObject(item, itemType); | |||
| var localName = q.LocalName; | |||
| Decorator.Enclose(w).WriteObject(item, itemType, opts => opts.Settings.RootName = new XmlQualifiedEntity(localName)); | |||
| } | |||
| else | |||
| { | |||
| writer.WriteValue(item); | |||
| w.WriteElementString(q.LocalName, Convert.ToString(item, CultureInfo.InvariantCulture)); | |||
| } | |||
There was a problem hiding this comment.
When flattenItems is enabled the writer uses q.LocalName / WriteElementString and constructs new XmlQualifiedEntity instances with only the local name. If q includes a namespace/prefix (e.g., via [XmlElement(Namespace=...)]), this drops that information and can produce elements in the wrong namespace. Prefer writing elements using the full qualified name (prefix/local-name/namespace) and propagate the namespace when creating root names for nested WriteObject calls.
| var existing = Decorator.Enclose(Settings.Converters).FirstOrDefaultWriterConverter(typeof(IEnumerable)); | ||
| if (existing != null) { Settings.Converters.Remove(existing); } | ||
| Decorator.Enclose(Settings.Converters).AddEnumerableConverter(flattenItems: true); |
There was a problem hiding this comment.
RefreshWithConverterDependencies removes the first IEnumerable writer converter it finds and then appends the flattened enumerable converter at the end. Because converter selection is order-dependent (FirstOrDefaultWriterConverter), the newly added flattened converter is not guaranteed to be used if another IEnumerable-capable converter remains earlier in the list. Consider inserting the flattened converter at the front (or removing/replacing all matching enumerable converters) so FlattenCollectionItems reliably takes effect without depending on converter ordering.
| var existing = Decorator.Enclose(Settings.Converters).FirstOrDefaultWriterConverter(typeof(IEnumerable)); | |
| if (existing != null) { Settings.Converters.Remove(existing); } | |
| Decorator.Enclose(Settings.Converters).AddEnumerableConverter(flattenItems: true); | |
| var converters = Decorator.Enclose(Settings.Converters); | |
| while (true) | |
| { | |
| var existing = converters.FirstOrDefaultWriterConverter(typeof(IEnumerable)); | |
| if (existing == null) { break; } | |
| Settings.Converters.Remove(existing); | |
| } | |
| converters.AddEnumerableConverter(flattenItems: true); |
| @@ -118,38 +122,84 @@ public static IDecorator<IList<XmlConverter>> AddEnumerableConverter(this IDecor | |||
| var valueValue = valueProperty.GetValue(element, null); | |||
| var valuePropertyType = valueProperty.PropertyType; | |||
| if (valuePropertyType == typeof(object) && valueValue != null) { valuePropertyType = valueValue.GetType(); } | |||
| writer.WriteStartElement("Item"); | |||
| writer.WriteAttributeString("name", keyValue.ToString()); | |||
| var keyName = Decorator.Enclose(keyValue.ToString()).SanitizeXmlElementName(); | |||
| if (Decorator.Enclose(valuePropertyType).IsComplex()) | |||
| { | |||
| Decorator.Enclose(writer).WriteObject(valueValue, valuePropertyType); | |||
| Decorator.Enclose(w).WriteObject(valueValue, valuePropertyType, opts => opts.Settings.RootName = new XmlQualifiedEntity(keyName)); | |||
| } | |||
| else | |||
| { | |||
| writer.WriteValue(valueValue); | |||
| w.WriteElementString(keyName, Convert.ToString(valueValue, CultureInfo.InvariantCulture)); | |||
| } | |||
| writer.WriteEndElement(); | |||
| } | |||
| w.WriteEndElement(); | |||
| } | |||
| else | |||
| { | |||
| foreach (var item in sequence) | |||
| foreach (var item in o) | |||
| { | |||
| if (item == null) { continue; } | |||
| var itemType = item.GetType(); | |||
| writer.WriteStartElement("Item"); | |||
| if (Decorator.Enclose(itemType).IsComplex()) | |||
| { | |||
| Decorator.Enclose(writer).WriteObject(item, itemType); | |||
| var localName = q.LocalName; | |||
| Decorator.Enclose(w).WriteObject(item, itemType, opts => opts.Settings.RootName = new XmlQualifiedEntity(localName)); | |||
| } | |||
| else | |||
| { | |||
| writer.WriteValue(item); | |||
| w.WriteElementString(q.LocalName, Convert.ToString(item, CultureInfo.InvariantCulture)); | |||
| } | |||
| writer.WriteEndElement(); | |||
| } | |||
| } | |||
There was a problem hiding this comment.
In the flattenItems && q != null branch for non-dictionary sequences, no container/root element is written (it emits repeated <q.LocalName> elements). If this converter is used at the document root and Settings.RootName is set (so q is non-null), the output will contain multiple top-level elements (invalid XML for ConformanceLevel.Document). Consider ensuring a single root/container element is written when w.WriteState == WriteState.Start (or otherwise when not already inside a parent element), even in flattened mode.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Directory.Packages.props`:
- Around line 9-14: Update the PackageVersion entries for
Codebelt.Extensions.Xunit and Codebelt.Extensions.BenchmarkDotNet.Console to use
existing NuGet versions: change the Version value for the PackageVersion with
Include="Codebelt.Extensions.Xunit" from 11.0.6 to 11.0.5, and change the
Version value for the PackageVersion with
Include="Codebelt.Extensions.BenchmarkDotNet.Console" from 1.2.3 to 1.2.2 so the
project restores successfully.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.docfx/Dockerfile.docfx.github/workflows/service-update.ymlDirectory.Packages.props
💤 Files with no reviewable changes (1)
- .github/workflows/service-update.yml
✅ Files skipped from review due to trivial changes (1)
- .docfx/Dockerfile.docfx
| <PackageVersion Include="Codebelt.Extensions.BenchmarkDotNet.Console" Version="1.2.3" /> | ||
| <PackageVersion Include="Codebelt.Extensions.Xunit" Version="11.0.6" /> | ||
| <PackageVersion Include="Codebelt.Extensions.Xunit.Hosting" Version="11.0.6" /> | ||
| <PackageVersion Include="Codebelt.Extensions.Xunit.Hosting.AspNetCore" Version="11.0.6" /> | ||
| <PackageVersion Include="Meziantou.Xunit.v3.ParallelTestFramework" Version="1.0.6" /> | ||
| <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" /> | ||
| <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify that the updated package versions exist on NuGet
packages=(
"Codebelt.Extensions.BenchmarkDotNet.Console:1.2.3"
"Codebelt.Extensions.Xunit:11.0.6"
"Codebelt.Extensions.Xunit.Hosting:11.0.6"
"Codebelt.Extensions.Xunit.Hosting.AspNetCore:11.0.6"
"Microsoft.NET.Test.Sdk:18.3.0"
)
for pkg in "${packages[@]}"; do
name="${pkg%%:*}"
version="${pkg##*:}"
echo "Checking $name version $version..."
status=$(curl -s -o /dev/null -w "%{http_code}" "https://api.nuget.org/v3-flatcontainer/${name,,}/${version}/${name,,}.nuspec")
if [ "$status" = "200" ]; then
echo " ✓ Available"
else
echo " ✗ Not found (HTTP $status)"
fi
doneRepository: codebeltnet/cuemon
Length of output: 1778
🌐 Web query:
Codebelt.Extensions.Xunit 11.0.6 nuget
💡 Result:
-
Codebelt.Extensions.Xunit: as of Feb 15, 2026, the newest version shown on NuGet is 11.0.5 (there is no 11.0.6 listed for this package). [1] (packages.nuget.org)- Install:
dotnet add package Codebelt.Extensions.Xunit --version 11.0.5[1] (packages.nuget.org)
- Install:
-
Codebelt.Extensions.Xunit.Hosting.AspNetCore: version 11.0.6 is available (last updated Feb 20, 2026). [2] (nugetprodusnc.azure-api.net)- Install:
dotnet add package Codebelt.Extensions.Xunit.Hosting.AspNetCore --version 11.0.6[2] (nugetprodusnc.azure-api.net)
- Install:
Sources
- NuGet package page/version list for
Codebelt.Extensions.Xunit(shows latest 11.0.5). (packages.nuget.org) - NuGet feed/page for
Codebelt.Extensions.Xunit.Hosting.AspNetCore11.0.6 (shows last updated 2/20/2026). (nugetprodusnc.azure-api.net)
Citations:
- 1: https://packages.nuget.org/packages/Codebelt.Extensions.Xunit/9.1.3
- 2: https://packages.nuget.org/packages/Codebelt.Extensions.Xunit/9.1.3
- 3: https://nugetprodusnc.azure-api.net/packages/Codebelt.Extensions.Xunit.Hosting.AspNetCore/?utm_source=openai
- 4: https://nugetprodusnc.azure-api.net/packages/Codebelt.Extensions.Xunit.Hosting.AspNetCore/?utm_source=openai
- 5: https://packages.nuget.org/packages/Codebelt.Extensions.Xunit/9.1.3
- 6: https://nugetprodusnc.azure-api.net/packages/Codebelt.Extensions.Xunit.Hosting.AspNetCore/?utm_source=openai
🌐 Web query:
Codebelt.Extensions.BenchmarkDotNet.Console 1.2.3 nuget
💡 Result:
I couldn’t find any NuGet release Codebelt.Extensions.BenchmarkDotNet.Console version 1.2.3.
What is discoverable is that the package exists and the latest published version appears to be 1.2.2 (with 5 versions total). [1] The package description shown on NuGet (via “Used By” metadata) is: “structured and opinionated console-hosted execution model for BenchmarkDotNet.” [2]
Install the latest known version:
dotnet add package Codebelt.Extensions.BenchmarkDotNet.Console --version 1.2.2Sources: [1] [2]
🌐 Web query:
Codebelt.Extensions.Xunit.Hosting 11.0.6 nuget
💡 Result:
Codebelt.Extensions.Xunit.Hosting v11.0.6 is available on NuGet, with Last Updated: 2026-02-20 (per NuGet gallery listing). [1]
Install:
dotnet add package Codebelt.Extensions.Xunit.Hosting --version 11.0.6NuGet.org’s main package page (as crawled) currently shows the latest stable as 11.0.4 and documents that the package targets .NET 9.0 and .NET Standard 2.0 (and is compatible with .NET 10+). [2]
Sources: [1] [2]
🌐 Web query:
Microsoft.NET.Test.Sdk 18.3.0 nuget
💡 Result:
Microsoft.NET.Test.Sdk v18.3.0 is available on NuGet (last updated/published Feb 24, 2026) and provides the MSBuild targets/properties used for building/running .NET test projects. [1]
Install
- .NET CLI:
dotnet add package Microsoft.NET.Test.Sdk --version 18.3.0
csproj:<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
[1]
Notable dependencies (from the NuGet listing)
Microsoft.CodeCoverage (>= 18.3.0)Microsoft.TestPlatform.TestHost (>= 18.3.0)(fornet8.0) [1]
Revert versions for Codebelt.Extensions.Xunit and Codebelt.Extensions.BenchmarkDotNet.Console—they do not exist on NuGet.
- Codebelt.Extensions.Xunit: Maximum available version is 11.0.5, not 11.0.6
- Codebelt.Extensions.BenchmarkDotNet.Console: Maximum available version is 1.2.2, not 1.2.3
The other packages are correct:
- Codebelt.Extensions.Xunit.Hosting: 11.0.6 ✓
- Codebelt.Extensions.Xunit.Hosting.AspNetCore: 11.0.6 ✓
- Microsoft.NET.Test.Sdk: 18.3.0 ✓
Correct lines 9 and 10 to reference the actual available versions to prevent build failures.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Directory.Packages.props` around lines 9 - 14, Update the PackageVersion
entries for Codebelt.Extensions.Xunit and
Codebelt.Extensions.BenchmarkDotNet.Console to use existing NuGet versions:
change the Version value for the PackageVersion with
Include="Codebelt.Extensions.Xunit" from 11.0.6 to 11.0.5, and change the
Version value for the PackageVersion with
Include="Codebelt.Extensions.BenchmarkDotNet.Console" from 1.2.3 to 1.2.2 so the
project restores successfully.
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (2)
.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt (1)
1-1: Remove the UTF-8 BOM from the release-notes file.Line 1 appears to start with a BOM character (
), which can cause noisy diffs/tooling inconsistencies in plain text files.Suggested cleanup
-Version: 10.4.0 +Version: 10.4.0🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt at line 1, The release notes file PackageReleaseNotes.txt contains a leading UTF-8 BOM before the first line "Version: 10.4.0"; remove the BOM so the file starts with the letter 'V' (e.g., re-save the file as UTF-8 without BOM or strip the BOM byte), verify the first line reads exactly "Version: 10.4.0", and commit the cleaned file to avoid noisy diffs/tooling issues..nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt (1)
1-1: Remove the UTF-8 BOM prefix on Line 1.The hidden BOM character before
Version: 10.4.0is unnecessary in this text file and can cause avoidable diff/formatting noise across tools.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt at line 1, Remove the hidden UTF-8 BOM at the start of the file by re-saving the file without a BOM so the first character is the visible text "Version: 10.4.0"; open the PackageReleaseNotes.txt containing "Version: 10.4.0" in your editor and choose "UTF-8 without BOM" (or run a tool/command to strip the BOM) and commit the cleaned file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/prompts/nuget-pouplate.prompt.md:
- Line 34: Fix the typo in the strict rule wording by replacing the misspelled
token "Alaways" with "Always" in the sentence "Alaways end with a newline
followed by spacer lines (`U+00A0`) between sections." Ensure the corrected
wording reads "Always end with a newline followed by spacer lines (`U+00A0`)
between sections." and keep the surrounding punctuation and formatting
unchanged.
In @.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt:
- Around line 1-6: Update the 10.4.0 release-note block to document the new
public API surface introduced by this PR: add short bullets describing
FlattenCollectionItems (its purpose and effect on serialization),
AddMinimalXmlOptions (what it configures and where to call it), and the new
flattened enumerable serialization behavior (how collections are serialized
differently now). Ensure each bullet is concise and consumer-facing (name +
one-line description) and place them under the 10.4.0 header alongside the
existing ALM note so users can discover these API changes.
In @.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt:
- Around line 1-6: Update the Version: 10.4.0 release notes block to include the
missing public API notes: add a short summary of the new XML-related and
minimal-API surface area introduced in this release (mention the user-visible
types/members or feature names added/changed), list any public API additions or
breaking changes, and include short usage/impact notes and migration guidance;
ensure the Version: 10.4.0 header in PackageReleaseNotes.txt contains the new
API bullet points consistent with the project's release-note format and coding
guidelines.
In @.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt:
- Around line 1-6: Update the .nuget package release notes to document the
public API changes introduced in 10.4.0: add a "Features" or "Improvements"
section to the .nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt entry and list
the new user-facing APIs and behavior changes such as FlattenCollectionItems,
AddMinimalXmlOptions, and the XML flattening behavior changes (describe concise
intent/impact of each item), ensuring the release note clearly separates
dependency upgrades from API/behavior changes.
In @.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt:
- Around line 1-6: The release notes currently omit new public APIs; update
.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt to list and
document the added extension methods: AssemblyExtensions.GetCacheValidator(),
DateTimeExtensions.GetCacheValidator() (both overloads),
FileInfoExtensions.GetCacheValidator(), and the ten overloads of
ChecksumBuilderExtensions.CombineWith<T>() (including the byte[] and
numeric-type overloads). Add short descriptive bullets for each symbol
indicating purpose and overload counts, and ensure they appear under the ALM or
a new "ADDED" section so the new public API surface is clearly recorded.
In @.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt:
- Around line 1-6: Update the 10.4.0 entry in
.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt to include explicit bullets
for the public API changes introduced by this PR: add a short bullet describing
the new XML options type (mention the type name introduced in this PR), a bullet
for the new extension method that configures those XML options (mention the
extension method name), and a bullet for the new serialization behavior toggles
that change default serialization behavior (mention the toggle property/method
names); keep each bullet concise, follow the existing release-note style, and
ensure the notes call out these are public API additions/behavior changes.
In @.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt:
- Around line 1-6: Update the PackageReleaseNotes for
Cuemon.Extensions.Reflection under the existing "Version: 10.4.0" heading to
include explicit API/XML-facing changes (not just dependency updates): enumerate
each public API change (types, members, signatures, removals, behavioral notes)
introduced in 10.4.0 so consumers can see breaking/added/changed APIs, following
the repo guideline to update per-package release notes; ensure the "Version:
10.4.0" block in PackageReleaseNotes.txt lists these API-level entries in
addition to the ALM dependency note.
In `@CHANGELOG.md`:
- Line 27: Remove the empty bullet from the 10.4.0 "Changed" section in
CHANGELOG.md by deleting the blank list item so the changelog renders correctly;
locate the "10.4.0" header and its "Changed" subsection and remove the stray "-"
(empty bullet) entry.
---
Nitpick comments:
In @.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt:
- Line 1: Remove the hidden UTF-8 BOM at the start of the file by re-saving the
file without a BOM so the first character is the visible text "Version: 10.4.0";
open the PackageReleaseNotes.txt containing "Version: 10.4.0" in your editor and
choose "UTF-8 without BOM" (or run a tool/command to strip the BOM) and commit
the cleaned file.
In @.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt:
- Line 1: The release notes file PackageReleaseNotes.txt contains a leading
UTF-8 BOM before the first line "Version: 10.4.0"; remove the BOM so the file
starts with the letter 'V' (e.g., re-save the file as UTF-8 without BOM or strip
the BOM byte), verify the first line reads exactly "Version: 10.4.0", and commit
the cleaned file to avoid noisy diffs/tooling issues.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (44)
.github/prompts/nuget-pouplate.prompt.md.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt.nuget/Cuemon.Core.App/PackageReleaseNotes.txt.nuget/Cuemon.Core/PackageReleaseNotes.txt.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt.nuget/Cuemon.Data/PackageReleaseNotes.txt.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt.nuget/Cuemon.IO/PackageReleaseNotes.txt.nuget/Cuemon.Net/PackageReleaseNotes.txt.nuget/Cuemon.Resilience/PackageReleaseNotes.txt.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt.nuget/Cuemon.Threading/PackageReleaseNotes.txt.nuget/Cuemon.Xml/PackageReleaseNotes.txtCHANGELOG.md
✅ Files skipped from review due to trivial changes (5)
- .nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt
- .nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt
- .nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt
- .nuget/Cuemon.Net/PackageReleaseNotes.txt
- .nuget/Cuemon.Threading/PackageReleaseNotes.txt
| - Prefer imperative, product-facing summaries over raw commit text. | ||
| - Mention concrete type/member names and namespace when identifiable, matching existing tone. | ||
| - Preserve NBSP-only spacer lines (`U+00A0`) between sections. | ||
| - Alaways end with a newline followed by spacer lines (`U+00A0`) between sections. |
There was a problem hiding this comment.
Fix typo in strict rule wording (Line 34).
“Alaways” should be “Always” to avoid ambiguity in an instruction marked as strict.
✏️ Proposed fix
-- Alaways end with a newline followed by spacer lines (`U+00A0`) between sections.
+- Always end with a newline followed by spacer lines (`U+00A0`) between sections.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - Alaways end with a newline followed by spacer lines (`U+00A0`) between sections. | |
| - Always end with a newline followed by spacer lines (`U+00A0`) between sections. |
🧰 Tools
🪛 LanguageTool
[grammar] ~34-~34: Ensure spelling is correct
Context: ...er lines (U+00A0) between sections. - Alaways end with a newline followed by spacer l...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/prompts/nuget-pouplate.prompt.md at line 34, Fix the typo in the
strict rule wording by replacing the misspelled token "Alaways" with "Always" in
the sentence "Alaways end with a newline followed by spacer lines (`U+00A0`)
between sections." Ensure the corrected wording reads "Always end with a newline
followed by spacer lines (`U+00A0`) between sections." and keep the surrounding
punctuation and formatting unchanged.
| Version: 10.4.0 | ||
| Availability: .NET 10 and .NET 9 | ||
|
|
||
| # ALM | ||
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | ||
|
|
There was a problem hiding this comment.
Document the 10.4.0 public API changes in this package’s release notes.
The new 10.4.0 block currently lists only dependency upgrades, but this PR introduces user-facing XML/minimal-API functionality. Please add explicit API notes (e.g., FlattenCollectionItems, AddMinimalXmlOptions, and flattened enumerable serialization behavior) so consumers can discover the change from package notes.
Proposed release-note addition
Version: 10.4.0
Availability: .NET 10 and .NET 9
+# API
+- ADDED `XmlSerializerOptions.FlattenCollectionItems` to enable flattened collection item serialization.
+- ADDED `IServiceCollection.AddMinimalXmlOptions(...)` for minimal API XML formatter registration.
+- CHANGED enumerable XML conversion to support flattened output for collections/dictionaries when enabled.
+
# ALM
- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs)As per coding guidelines, “Update per-package release notes in .nuget/<PackageName>/PackageReleaseNotes.txt for public API changes”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt around lines 1 - 6,
Update the 10.4.0 release-note block to document the new public API surface
introduced by this PR: add short bullets describing FlattenCollectionItems (its
purpose and effect on serialization), AddMinimalXmlOptions (what it configures
and where to call it), and the new flattened enumerable serialization behavior
(how collections are serialized differently now). Ensure each bullet is concise
and consumer-facing (name + one-line description) and place them under the
10.4.0 header alongside the existing ALM note so users can discover these API
changes.
| Version: 10.4.0 | ||
| Availability: .NET 10 and .NET 9 | ||
|
|
||
| # ALM | ||
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | ||
|
|
There was a problem hiding this comment.
Add the missing 10.4.0 public API notes to this package release entry.
The new 10.4.0 block only mentions dependency upgrades, but this release includes user-visible XML/minimal-API features. Please document those API changes in this package’s release notes.
Proposed release-notes update
Version: 10.4.0
Availability: .NET 10 and .NET 9
# ALM
- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs)
+
+# Improvements
+- ADDED `AddMinimalXmlOptions(IServiceCollection, Action<XmlFormatterOptions>?)` extension for minimal API XML formatter registration
+- ADDED `XmlSerializerOptions.FlattenCollectionItems` to control flattened collection item element naming
+- CHANGED XML enumerable/dictionary serialization to support flattened item output when enabled
+- CHANGED default XML conversion flow to avoid redundant child element wrapping when a dedicated converter existsAs per coding guidelines: “.nuget/**/*.txt: Update per-package release notes in .nuget/<PackageName>/PackageReleaseNotes.txt for public API changes”.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Version: 10.4.0 | |
| Availability: .NET 10 and .NET 9 | |
| # ALM | |
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | |
| Version: 10.4.0 | |
| Availability: .NET 10 and .NET 9 | |
| # ALM | |
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | |
| # Improvements | |
| - ADDED `AddMinimalXmlOptions(IServiceCollection, Action<XmlFormatterOptions>?)` extension for minimal API XML formatter registration | |
| - ADDED `XmlSerializerOptions.FlattenCollectionItems` to control flattened collection item element naming | |
| - CHANGED XML enumerable/dictionary serialization to support flattened item output when enabled | |
| - CHANGED default XML conversion flow to avoid redundant child element wrapping when a dedicated converter exists |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt around lines 1 - 6,
Update the Version: 10.4.0 release notes block to include the missing public API
notes: add a short summary of the new XML-related and minimal-API surface area
introduced in this release (mention the user-visible types/members or feature
names added/changed), list any public API additions or breaking changes, and
include short usage/impact notes and migration guidance; ensure the Version:
10.4.0 header in PackageReleaseNotes.txt contains the new API bullet points
consistent with the project's release-note format and coding guidelines.
| Version: 10.4.0 | ||
| Availability: .NET 10 and .NET 9 | ||
|
|
||
| # ALM | ||
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | ||
|
|
There was a problem hiding this comment.
Document the 10.4.0 public API changes in release notes.
The new 10.4.0 entry only lists dependency upgrades, but this PR introduces user-facing API/features (e.g., FlattenCollectionItems, AddMinimalXmlOptions, XML flattening behavior changes). Please add those under feature/improvement sections so the package notes reflect the actual public surface changes.
Suggested update shape
Version: 10.4.0
Availability: .NET 10 and .NET 9
# ALM
- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs)
+
+# New Features
+- ADDED AddMinimalXmlOptions extension method for IServiceCollection in Cuemon.AspNetCore XML integration
+
+# Improvements
+- EXTENDED XmlSerializerOptions with FlattenCollectionItems to control flattened collection element naming
+- CHANGED XML enumerable/dictionary conversion and formatter behavior to support flattened item serialization
+- CHANGED default XML conversion flow to avoid redundant child element wrapping when dedicated converters existAs per coding guidelines: “.nuget/**/*.txt: Update per-package release notes in .nuget/<PackageName>/PackageReleaseNotes.txt for public API changes”.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Version: 10.4.0 | |
| Availability: .NET 10 and .NET 9 | |
| # ALM | |
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | |
| Version: 10.4.0 | |
| Availability: .NET 10 and .NET 9 | |
| # ALM | |
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | |
| # New Features | |
| - ADDED AddMinimalXmlOptions extension method for IServiceCollection in Cuemon.AspNetCore XML integration | |
| # Improvements | |
| - EXTENDED XmlSerializerOptions with FlattenCollectionItems to control flattened collection element naming | |
| - CHANGED XML enumerable/dictionary conversion and formatter behavior to support flattened item serialization | |
| - CHANGED default XML conversion flow to avoid redundant child element wrapping when dedicated converters exist |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt around lines 1 - 6, Update
the .nuget package release notes to document the public API changes introduced
in 10.4.0: add a "Features" or "Improvements" section to the
.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt entry and list the new
user-facing APIs and behavior changes such as FlattenCollectionItems,
AddMinimalXmlOptions, and the XML flattening behavior changes (describe concise
intent/impact of each item), ensuring the release note clearly separates
dependency upgrades from API/behavior changes.
| Version: 10.4.0 | ||
| Availability: .NET 10, .NET 9 and .NET Standard 2.0 | ||
|
|
||
| # ALM | ||
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find the source directory for Cuemon.Extensions.Data.Integrity package
fd -type d "Data.Integrity" src/Repository: codebeltnet/cuemon
Length of output: 232
🏁 Script executed:
# List files in the src directory to understand structure
ls -la src/ | head -20Repository: codebeltnet/cuemon
Length of output: 1509
🏁 Script executed:
# Find all csproj files to identify package projects
fd -e csproj src/ | grep -i "data.integrity"Repository: codebeltnet/cuemon
Length of output: 383
🏁 Script executed:
# Check git status and changes for this specific package
git diff --name-status HEAD~1..HEAD 2>/dev/null | head -30 || echo "Git diff not available, trying alternative approach"Repository: codebeltnet/cuemon
Length of output: 44
🏁 Script executed:
# List the .nuget directory to see what packages are documented
ls -la .nuget/Repository: codebeltnet/cuemon
Length of output: 3424
🏁 Script executed:
# Find csproj files for the Data.Integrity packages
find src -name "*Data.Integrity*.csproj"Repository: codebeltnet/cuemon
Length of output: 193
🏁 Script executed:
# List contents of the source directory for Extensions.Data.Integrity
ls -la src/Cuemon.Extensions.Data.Integrity/ 2>/dev/null || echo "Directory not found at that path"Repository: codebeltnet/cuemon
Length of output: 621
🏁 Script executed:
# Search for all source files related to Data.Integrity packages
fd "Data.Integrity" src/ --full-pathRepository: codebeltnet/cuemon
Length of output: 1696
🏁 Script executed:
# Check git log to see what changed in Data.Integrity packages
git log --oneline --name-status HEAD~5..HEAD 2>/dev/null | grep -i "data.integrity" || echo "Checking alternative approach"Repository: codebeltnet/cuemon
Length of output: 91
🏁 Script executed:
# List all directories under src to find the correct path
ls -d src/Cuemon.Extensions.Data* 2>/dev/null || ls -d src/*Data* 2>/dev/nullRepository: codebeltnet/cuemon
Length of output: 125
🏁 Script executed:
# Check git diff for changes to Cuemon.Extensions.Data.Integrity files
git diff HEAD~1 src/Cuemon.Extensions.Data.Integrity/ 2>/dev/null | head -200Repository: codebeltnet/cuemon
Length of output: 44
🏁 Script executed:
# Check if there are any additions/modifications to public APIs (methods, classes)
git diff HEAD~1 src/Cuemon.Extensions.Data.Integrity/ 2>/dev/null | grep -E "^\+.*public|^\+.*class|^\+.*interface|^\+.*method" | head -50Repository: codebeltnet/cuemon
Length of output: 44
🏁 Script executed:
# Alternative: Check the git status of these files
git status src/Cuemon.Extensions.Data.Integrity/ 2>/dev/nullRepository: codebeltnet/cuemon
Length of output: 127
🏁 Script executed:
# Check the actual content of the source files to understand what they export
head -50 src/Cuemon.Extensions.Data.Integrity/AssemblyExtensions.csRepository: codebeltnet/cuemon
Length of output: 1711
🏁 Script executed:
# Get a full picture of changes - check what version control shows
git log --oneline -1Repository: codebeltnet/cuemon
Length of output: 103
🏁 Script executed:
# Check git log to see recent commits that might have touched this package
git log --oneline --all -20 | head -20Repository: codebeltnet/cuemon
Length of output: 915
🏁 Script executed:
# Try to find changes by comparing with main or master branch
git diff main...HEAD src/Cuemon.Extensions.Data.Integrity/ 2>/dev/null | head -300Repository: codebeltnet/cuemon
Length of output: 44
🏁 Script executed:
# Alternative: check if there are any recent commits
git log --oneline src/Cuemon.Extensions.Data.Integrity/ 2>/dev/null | head -10Repository: codebeltnet/cuemon
Length of output: 103
🏁 Script executed:
# Check file content to understand if there are recent modifications
wc -l src/Cuemon.Extensions.Data.Integrity/*.csRepository: codebeltnet/cuemon
Length of output: 340
🏁 Script executed:
# Check the csproj file to see dependencies and package info
cat src/Cuemon.Extensions.Data.Integrity/Cuemon.Extensions.Data.Integrity.csprojRepository: codebeltnet/cuemon
Length of output: 714
🏁 Script executed:
# Check which files were changed in the current commit
git show --name-status HEAD | head -50Repository: codebeltnet/cuemon
Length of output: 2737
🏁 Script executed:
# Check files modified in recent commits to understand the PR context
git diff HEAD~5..HEAD --name-only | grep -i "data.integrity"Repository: codebeltnet/cuemon
Length of output: 254
🏁 Script executed:
# Look at the .nuget file itself to see if there are comments about changes
cat .nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txtRepository: codebeltnet/cuemon
Length of output: 3313
🏁 Script executed:
# Check if there are any other package release notes files to compare format
head -20 .nuget/Cuemon.Core/PackageReleaseNotes.txtRepository: codebeltnet/cuemon
Length of output: 935
🏁 Script executed:
# Check the commit details more thoroughly - is this really the right commit?
git show --stat HEAD | head -100Repository: codebeltnet/cuemon
Length of output: 6149
🏁 Script executed:
# Verify: did any Cuemon.Extensions.Data.Integrity source files change in this commit?
git show HEAD -- src/Cuemon.Extensions.Data.Integrity/Repository: codebeltnet/cuemon
Length of output: 18091
Update release notes to document new public extension methods.
The package includes significant new public APIs that are not documented:
AssemblyExtensions.GetCacheValidator()ChecksumBuilderExtensions.CombineWith<T>()(10 overloads for different numeric types and byte[])DateTimeExtensions.GetCacheValidator()(2 overloads)FileInfoExtensions.GetCacheValidator()
These extension methods represent new public API surface and must be documented in the release notes per coding guidelines.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt around lines
1 - 6, The release notes currently omit new public APIs; update
.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt to list and
document the added extension methods: AssemblyExtensions.GetCacheValidator(),
DateTimeExtensions.GetCacheValidator() (both overloads),
FileInfoExtensions.GetCacheValidator(), and the ten overloads of
ChecksumBuilderExtensions.CombineWith<T>() (including the byte[] and
numeric-type overloads). Add short descriptive bullets for each symbol
indicating purpose and overload counts, and ensure they appear under the ALM or
a new "ADDED" section so the new public API surface is clearly recorded.
| Version: 10.4.0 | ||
| Availability: .NET 10, .NET 9 and .NET Standard 2.0 | ||
|
|
||
| # ALM | ||
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | ||
|
|
There was a problem hiding this comment.
Add the missing 10.4.0 public API notes.
The 10.4.0 section currently states only dependency updates, but this PR introduces public API changes (new XML options/extension method and serialization behavior toggles). Please add explicit release-note bullets for those API additions/behavior changes in this package’s 10.4.0 entry.
As per coding guidelines: "Update per-package release notes in .nuget/<PackageName>/PackageReleaseNotes.txt for public API changes". Based on learnings: "Applies to .nuget/**/*.txt : Update per-package release notes in .nuget/<PackageName>/PackageReleaseNotes.txt for public API changes".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt around lines 1 - 6,
Update the 10.4.0 entry in .nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt
to include explicit bullets for the public API changes introduced by this PR:
add a short bullet describing the new XML options type (mention the type name
introduced in this PR), a bullet for the new extension method that configures
those XML options (mention the extension method name), and a bullet for the new
serialization behavior toggles that change default serialization behavior
(mention the toggle property/method names); keep each bullet concise, follow the
existing release-note style, and ensure the notes call out these are public API
additions/behavior changes.
| Version: 10.4.0 | ||
| Availability: .NET 10, .NET 9 and .NET Standard 2.0 | ||
|
|
||
| # ALM | ||
| - CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) | ||
|
|
There was a problem hiding this comment.
Document the 10.4.0 public API changes in this package’s release notes.
The new 10.4.0 block currently lists only dependency upgrades, but this release includes public XML/API-facing changes and should explicitly note them for consumers (not just ALM dependency text). Please add API-level entries under 10.4.0 for the relevant changes exposed by this package.
As per coding guidelines: "Update per-package release notes in .nuget/<PackageName>/PackageReleaseNotes.txt for public API changes." Based on learnings: "Applies to .nuget/**/*.txt : Update per-package release notes in .nuget/<PackageName>/PackageReleaseNotes.txt for public API changes".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt around lines 1 -
6, Update the PackageReleaseNotes for Cuemon.Extensions.Reflection under the
existing "Version: 10.4.0" heading to include explicit API/XML-facing changes
(not just dependency updates): enumerate each public API change (types, members,
signatures, removals, behavioral notes) introduced in 10.4.0 so consumers can
see breaking/added/changed APIs, following the repo guideline to update
per-package release notes; ensure the "Version: 10.4.0" block in
PackageReleaseNotes.txt lists these API-level entries in addition to the ALM
dependency note.
| - `World` class in the Cuemon.Globalization namespace to exclude redundancies in `RegionInfo` handling, | ||
| - `XmlConverterExtensions` class in the Cuemon.Extensions.Xml.Serialization.Converters namespace to support flattening items when serializing in the `AddEnumerableConverter` method, | ||
| - `XmlSerializerOptions` class in the `Cuemon.Xml.Serialization` namespace was extended with `FlattenCollectionItems` property to control item flattening during enumerable XML serialization, | ||
| - |
There was a problem hiding this comment.
Remove the empty bullet in the 10.4.0 “Changed” section.
Line 27 introduces a blank list item, which renders as a malformed changelog entry.
✏️ Proposed fix
- `XmlSerializerOptions` class in the `Cuemon.Xml.Serialization` namespace was extended with `FlattenCollectionItems` property to control item flattening during enumerable XML serialization,
-- 🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@CHANGELOG.md` at line 27, Remove the empty bullet from the 10.4.0 "Changed"
section in CHANGELOG.md by deleting the blank list item so the changelog renders
correctly; locate the "10.4.0" header and its "Changed" subsection and remove
the stray "-" (empty bullet) entry.
|
|
@copilot open a new pull request to apply changes based on the comments in this thread |
|
@gimlichael I've opened a new pull request, #153, to work on those changes. Once the pull request is ready, I'll request review from you. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #152 +/- ##
==========================================
+ Coverage 80.66% 80.74% +0.07%
==========================================
Files 600 601 +1
Lines 18932 18998 +66
Branches 1949 1961 +12
==========================================
+ Hits 15272 15339 +67
+ Misses 3592 3591 -1
Partials 68 68 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|



This pull request introduces improvements to XML serialization, particularly around collection handling, and adds new extension methods and tests for ASP.NET Core integration. The main focus is on enabling "flattened" XML serialization for collections, where items are serialized as repeated elements named after their property rather than wrapped in generic "Item" elements. Additionally, a new extension method for registering XML formatter options in ASP.NET Core is added, along with comprehensive tests.
Enhancements to XML Collection Serialization:
FlattenCollectionItemsproperty toXmlSerializerOptionsto control whether collection items are serialized as repeated elements using the property name instead of a generic wrapper.flattenItemsparameter, enabling flattened serialization for both dictionaries and collections. [1] [2]XmlFormatterOptionsto respect theFlattenCollectionItemssetting and ensure the correct converter is used when this option is enabled.ASP.NET Core Integration:
AddMinimalXmlOptionsextension method forIServiceCollectionto simplify XML formatter registration in ASP.NET Core applications.Improvements to XML Converter Encapsulation:
DefaultXmlConverterto avoid duplicate XML element wrapping when a dedicated converter exists for a child node type, preventing redundant nesting in the output. [1] [2]Supporting Assets and Minor Cleanups:
RegionStats,WorldNode, etc.) for more robust XML serialization tests. [1] [2]These changes collectively improve the flexibility and usability of XML serialization in the codebase, especially for ASP.NET Core scenarios and complex collection structures.
Summary by CodeRabbit
New Features
Bug Fixes
Tests