From aaba2c05d9c58cfe6d39dd465682c044f21fcf9b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Sep 2025 17:09:22 +0000 Subject: [PATCH 1/2] Initial plan From 892ce6bd14e592abb07dcff47831d4213f509c67 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Sep 2025 17:19:09 +0000 Subject: [PATCH 2/2] Add breaking change documentation for System.IO.Packaging case-insensitive URI comparison in .NET 8 Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com> --- docs/core/compatibility/8.0.md | 1 + ...ystem-io-packaging-case-insensitive-uri.md | 54 +++++++++++++++++++ docs/core/compatibility/toc.yml | 2 + 3 files changed, 57 insertions(+) create mode 100644 docs/core/compatibility/core-libraries/8.0/system-io-packaging-case-insensitive-uri.md diff --git a/docs/core/compatibility/8.0.md b/docs/core/compatibility/8.0.md index 6c56c864ba3aa..b566f1e8ba1aa 100644 --- a/docs/core/compatibility/8.0.md +++ b/docs/core/compatibility/8.0.md @@ -57,6 +57,7 @@ If you're migrating an app to .NET 8, the breaking changes listed here might aff | [ITypeDescriptorContext nullable annotations](core-libraries/8.0/itypedescriptorcontext-props.md) | Source incompatible | | [Legacy Console.ReadKey removed](core-libraries/8.0/console-readkey-legacy.md) | Behavioral change | | [Method builders generate parameters with HasDefaultValue set to false](core-libraries/8.0/parameterinfo-hasdefaultvalue.md) | Behavioral change | +| [Package part URIs are now compared case-insensitively in System.IO.Packaging](core-libraries/8.0/system-io-packaging-case-insensitive-uri.md) | Behavioral change | | [ProcessStartInfo.WindowStyle honored when UseShellExecute is false](core-libraries/8.0/processstartinfo-windowstyle.md) | Behavioral change | | [RuntimeIdentifier returns platform for which runtime was built](core-libraries/8.0/runtimeidentifier.md) | Behavioral change | | [`Type.GetType` throws exception for all invalid element types](core-libraries/8.0/type-gettype.md) | Behavioral change | diff --git a/docs/core/compatibility/core-libraries/8.0/system-io-packaging-case-insensitive-uri.md b/docs/core/compatibility/core-libraries/8.0/system-io-packaging-case-insensitive-uri.md new file mode 100644 index 0000000000000..c9059b2ad9dd4 --- /dev/null +++ b/docs/core/compatibility/core-libraries/8.0/system-io-packaging-case-insensitive-uri.md @@ -0,0 +1,54 @@ +--- +title: "Breaking change: Package part URIs are now compared case-insensitively in System.IO.Packaging" +description: "Learn about the breaking change in .NET 8 where System.IO.Packaging now compares package part URIs case-insensitively to align with the OPC specification." +ms.date: 09/29/2024 +ai-usage: ai-generated +ms.custom: https://github.com/dotnet/runtime/issues/112783 +--- + +# Package part URIs are now compared case-insensitively in System.IO.Packaging + +Previously, part names and overrides that differed only by ASCII case (for example, `/part` vs `/PART`) were not considered equivalent in , even though the Open Packaging Conventions (OPC) specification requires case-insensitive equivalence (§7.2.3.5, ECMA-376). This change fixes the bug and brings .NET 5–9 in line with both .NET Framework and the OPC specification. + +## Version introduced + +.NET 8 + +## Previous behavior + +URI comparisons were case-sensitive. +Content type overrides failed if the casing differed between the part URI and the override entry. +Some non-compliant packages containing duplicate entries differing only in case (for example, `/part` and `/PART`) could be loaded, leading to ambiguous results. + +## New behavior + +URI comparisons are case-insensitive (). +Overrides with different casing now work as expected. +Non-compliant packages containing multiple entries that differ only by case are now rejected when opened. This aligns with .NET Framework and the OPC specification. + +## Type of breaking change + +This is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +This change aligns behavior with: + +- The OPC specification (case-insensitive URI equivalence is mandatory). +- Existing .NET Framework behavior, which already enforces case-insensitive matching. + +It prevents ambiguous lookups and ensures consistent results, and fixes [dotnet/runtime#112783](https://github.com/dotnet/runtime/issues/112783). + +## Recommended action + +Ensure that OPC packages do not contain part names differing only by case, as this is invalid per the OPC specification. + +If consuming packages that violate the specification: + +- Contact the package author to fix the package. +- If you need to read or inspect the contents, you can open the package as a ZIP archive. Unlike the Package API, ZIP archives do not enforce OPC rules and will allow you to access all entries, including those with conflicting case names. + +## Affected APIs + +- +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 33939a4065721..789a51226de3e 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -398,6 +398,8 @@ items: href: core-libraries/8.0/console-readkey-legacy.md - name: Method builders generate parameters with HasDefaultValue=false href: core-libraries/8.0/parameterinfo-hasdefaultvalue.md + - name: Package part URIs are now compared case-insensitively in System.IO.Packaging + href: core-libraries/8.0/system-io-packaging-case-insensitive-uri.md - name: ProcessStartInfo.WindowStyle honored when UseShellExecute is false href: core-libraries/8.0/processstartinfo-windowstyle.md - name: RuntimeIdentifier returns platform for which runtime was built