From 78631f51d4e665edfe35b4cc085fc4a797e3222f Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Mon, 13 Nov 2023 14:43:10 -0800 Subject: [PATCH 1/8] Add migration guide to v3.0 --- docs/migration/migrate-v2-to-v3.md | 117 +++++++++++++++++++++++++++++ docs/open-xml-sdk.md | 4 + docs/toc.yml | 2 + 3 files changed, 123 insertions(+) create mode 100644 docs/migration/migrate-v2-to-v3.md diff --git a/docs/migration/migrate-v2-to-v3.md b/docs/migration/migrate-v2-to-v3.md new file mode 100644 index 00000000..76bf0f55 --- /dev/null +++ b/docs/migration/migrate-v2-to-v3.md @@ -0,0 +1,117 @@ +--- +title: 'Migrate from v2.x to v3.0' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 11/01/2017 +ms.localizationpriority: medium +--- + +# Migration to v3.0.0 + +There are a number of breaking changes between v2.20.0 and v3.0.0 that may require source level changes. As a reminder, there are two kinds of breaking changes: + +1. **Binary**: When a binary can no longer be used as drop in replacement +2. **Source**: When the source no longer compiles + +The changes made in v3.0.0 were either a removal of obsoletions present in the SDK for a while or changes required for architectural reasons (most notably for better AOT support and trimming). Majority of these changes should be on the *binary* breaking change side, while still supporting compilation and expected behavior with your previous code. However, there are a few source breaking chnages to be made aware of. + +## Breaking Changes + +### .NET Standard 1.3 support has been dropped + +No targets still in support require .NET Standard 1.3 and can use .NET Standard 2.0 instead. The project still supports .NET Framework 3.5+ and any [.NET Standard 2.0 supported platform](/dotnet/standard/net-standard?tabs=net-standard-2-0). + +**Action needed**: If using .NET Standard 1.3, please upgrade to a supported version of .NET + +### Target frameworks have changed + +In order to simplify package creation, the TFMs built have been changed for some of the packages. However, there should be no apparent change to users as the overall supported platforms (besides .NET Standard 1.3 stated above) remains the same. + +**Action needed**: None + +### OpenXmlPart/OpenXmlContainer/OpenXmlPackage no longer have public constructors + +These never initialized correct behavior and should never have been exposed. + +**Action needed**: Use `.Create(...)` methods rather than constructor. + +### Supporting framework for OpenXML types is now in the DocumentFormat.OpenXml.Framework package + +Starting with v3.0.0, the supporting framework for the Open XML SDK is now within a standalone package, [DocumentFormat.OpenXml.Framework](https://www.nuget.org/packages/DocumentFormat.OpenXml.Framework). + +**Action needed**: If you would like to operate on just `OpenXmlPackage` types, you no longer need to bring in all the static classes and can just reference the framework library. + +### System.IO.Packaging is not directly used anymore + +There have been issues with getting behavior we need from the System.IO.Packaging namespace. Starting with v3.0, a new set of interfaces in the `DocumentFormat.OpenXml.Packaging` namespace will be used to access package properties. + +> NOTE: These types are currently marked as Obsolete, but only in the sense that we reserve the right to change their shape per feedback. Please be careful using these types as they may change in the future. At some point, we will remove the obsoletions and they will be considered stable APIs. + +**Action needed**: If using `OpenXmlPackage.Package`, the package returned is no longer of type `System.IO.Packaging.Package`, but of `DocumentFormat.OpenXml.Packaging.IPackage`. + +### Methods on parts to add child parts are now extension methods + +There was a number of duplicated methods that would add parts in well defined ways. In order to consolidate this, if a part supports `ISupportedRelationship`, extension methods can be written to support specific behavior that part can provide. Existing methods for this should transparently be retargeted to the new extension methods upon compilation. + +**Action needed**: None + +### OpenXmlAttribute is now a readonly struct + +This type used to have mutable getters and setters. As a struct, this was easy to misuse, and should have been made readonly from the start. + +**Action needed**: If expecting to mutate an OpenXmlAttribute in place, please create a new one instead. + +### EnumValue<TEnum> now contains structs + +Starting with v3.0.0, `EnumValue` wraps a custom type that contains the information about the enum value. Previously, these types were stored in enum values in the C# type system, but required reflection to access, causing very large AOT compiled applications. + +**Action needed**: Similar API surface is available, however the exposed enum values for this are no longer constants and will not be available in a few scenarios they had been (i.e. attribute values). + +### OpenXmlElementList is now a struct + +[OpenXmlElementList](/dotnet/api/documentformat.openxml.openxmlelementlist) is now a struct. It still implements `IEnumerable` in addition to `IReadOnlyList` where available. + +**Action needed**: None + +### IdPartPair is now a readonly struct + +This type is used to enumerate pairs within a part and caused many unnecessary allocations. This change should be transparent upon recompilation. + +**Action needed**: None + +### OpenXmlPartReader no longer knows about all parts + +In previous versions, [OpenXmlPartReader](/dotnet/api/documentformat.openxml.openxmlpartreader) knew about about all strongly typed part. In order to reduce coupling required for better AOT scenarios, we now have typed readers for known packages: `WordprocessingDocumentPartReader`, `SpreadsheetDocumentPartReader`, and `PresentationDocumentPartReader`. + +**Action needed**: Replace usage of `OpenXmlPartReader` with document specific readers if needed. If creating a part reader from a known package, please use the constructors that take an existing `OpenXmlPart` which will then create the expected strongly typed parts. + +### Attributes for schema information have been removed + +`SchemaAttrAttribute` and `ChildElementInfoAttribute` have been removed from types and the types themselves are no longer present. + +**Action needed**: If these types were required, please engage us at https://github.com/dotnet/open-xml-sdk to figure out the best way forward for you. + +### OpenXmlPackage.Close has been removed + +This did nothing useful besides call `.Dispose()`, but caused confusion about which should be called. This is now removed with the expectation of calling `.Dispose()`, preferably with the [using pattern](/dotnet/api/system.idisposable#using-an-object-that-implements-idisposable). + +**Action needed**: Remove call and ensure package is disposed properly + +### OpenXmlPackage.CanSave is now an instance property + +This property used to be a static property that was dependent on the framework. Now, it may change per-package instance depending on settings and backing store. + +**Action needed**: Replace usage of static property with instance. + +### OpenXmlPackage.PartExtensionProvider has been changed + +This property provided a dictionary that allowed access to change the extensions used. This is now backed by the `IPartExtensionFeature`. + +**Action needed**: Replace usage with `OpenXmlPackage.Features.GetRequired()`. + +### Packages with MarkupCompatibilityProcessMode.ProcessAllParts now actually process all parts + +Previously, there was a heuristic to potentially minimize processing if no parts had been loaded. However, this caused scenarios such as ones where someone manually edited the XML to not actually process upon saving. v3.0.0 fixes this behavior and processes all part if this has been opted in. diff --git a/docs/open-xml-sdk.md b/docs/open-xml-sdk.md index 425fe6f5..aa3a67de 100644 --- a/docs/open-xml-sdk.md +++ b/docs/open-xml-sdk.md @@ -56,6 +56,10 @@ Portions of ISO/IEC 29500:20081 are referenced in the SDK. - [Spreadsheets](spreadsheet/overview.md) - [Word processing](word/overview.md) +## Migrating from previous versions + +- [Migrating to v3.0.0 from v2.x](migration/migrate-v2-to-v3.md) + ## See also - [Open XML SDK for Microsoft Office](https://www.nuget.org/packages/DocumentFormat.OpenXml) diff --git a/docs/toc.yml b/docs/toc.yml index 1b0ae262..690b49e3 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -12,6 +12,8 @@ href: what-s-new-in-the-open-xml-sdk.md - name: Open XML SDK design considerations href: open-xml-sdk-design-considerations.md + - name: Migrating v2.x to v3.0 + href: migration/migrate-v2-to-v3.md - name: General items: - name: Overview From 3ab6af02ca4d624d5f4fd7fc3c43718e33bae92e Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Mon, 13 Nov 2023 15:10:47 -0800 Subject: [PATCH 2/8] add action --- docs/migration/migrate-v2-to-v3.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/migration/migrate-v2-to-v3.md b/docs/migration/migrate-v2-to-v3.md index 76bf0f55..3f9644f9 100644 --- a/docs/migration/migrate-v2-to-v3.md +++ b/docs/migration/migrate-v2-to-v3.md @@ -115,3 +115,5 @@ This property provided a dictionary that allowed access to change the extensions ### Packages with MarkupCompatibilityProcessMode.ProcessAllParts now actually process all parts Previously, there was a heuristic to potentially minimize processing if no parts had been loaded. However, this caused scenarios such as ones where someone manually edited the XML to not actually process upon saving. v3.0.0 fixes this behavior and processes all part if this has been opted in. + +**Action needed**: If you only want loaded parts to be processed, change to `MarkupCompatibilityProcessMode.ProcessLoadedPartsOnly` \ No newline at end of file From 75e7e340bd829e5e058eb959c490c12bb2d94a96 Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Mon, 13 Nov 2023 15:28:07 -0800 Subject: [PATCH 3/8] update obsolete --- docs/general/diagnosticids.md | 55 ++++++++++++++++++++++++++++++ docs/general/overview.md | 1 + docs/migration/migrate-v2-to-v3.md | 7 ++-- docs/toc.yml | 2 ++ 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 docs/general/diagnosticids.md diff --git a/docs/general/diagnosticids.md b/docs/general/diagnosticids.md new file mode 100644 index 00000000..980dfe52 --- /dev/null +++ b/docs/general/diagnosticids.md @@ -0,0 +1,55 @@ +--- +title: Diagnostic IDs +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 11/01/2017 +ms.localizationpriority: high +--- + +# Diagnostic IDs + +Diagnostic IDs are used to identify APIs or patterns that can raise compiler warnings or errors. This can be done via [ObsoleteAttribute](/dotnet/api/system.obsoleteattribute.diagnosticid) or [ExperimentalAttribute](/dotnet/api/system.diagnostics.codeanalysis.experimentalattribute). These can be suppressed at the consumer level for each diagnostic id. + +## OOXML0001 - IPackage related APIs are currently experimental + +As of v3.0, a new abstraction layer was added in between `System.IO.Packaging` and `DocumentFormat.OpenXml.Packaging.OpenXmlPackage`. This is currently experimental, but can be used if needed. This will be stabalized in a future release, and may or may not require code changes. + +## Suppress warnings + +It's recommended that you use an available workaround whenever possible. However, if you cannot change your code, you can suppress warnings through a `#pragma` directive or a `` project setting. If you must use the obsolete or experimental APIs and the `OOXMLXXXX` diagnostic does not surface as an error, you can suppress the warning in code or in your project file. + +To suppress the warnings in code: + +```csharp +// Disable the warning. +#pragma warning disable OOXML0001 + +// Code that uses obsolete or experimental API. +//... + +// Re-enable the warning. +#pragma warning restore OOXML0001 +``` + +To suppress the warnings in a project file: + +```xml + + + net6.0 + + $(NoWarn);OOXML0001 + + $(NoWarn);OOXML0001 + $(NoWarn);OTHER_WARNING + + $(NoWarn);OOXML0001;OTHER_WARNING + + +``` + +> [!NOTE] +> Suppressing warnings in this way only disables the obsoletion warnings you specify. It doesn't disable any other warnings, including obsoletion warnings with different diagnostic IDs. diff --git a/docs/general/overview.md b/docs/general/overview.md index 9ed40b3c..69067fd9 100644 --- a/docs/general/overview.md +++ b/docs/general/overview.md @@ -39,6 +39,7 @@ This section provides how-to topics for working with documents and packages usin - [Search and replace text in a document part](how-to-search-and-replace-text-in-a-document-part.md) +- [Diagnostic IDs](diagnosticids.md) ## Related sections diff --git a/docs/migration/migrate-v2-to-v3.md b/docs/migration/migrate-v2-to-v3.md index 3f9644f9..0ff664ac 100644 --- a/docs/migration/migrate-v2-to-v3.md +++ b/docs/migration/migrate-v2-to-v3.md @@ -48,7 +48,8 @@ Starting with v3.0.0, the supporting framework for the Open XML SDK is now withi There have been issues with getting behavior we need from the System.IO.Packaging namespace. Starting with v3.0, a new set of interfaces in the `DocumentFormat.OpenXml.Packaging` namespace will be used to access package properties. -> NOTE: These types are currently marked as Obsolete, but only in the sense that we reserve the right to change their shape per feedback. Please be careful using these types as they may change in the future. At some point, we will remove the obsoletions and they will be considered stable APIs. +> [!NOTE] +> These types are currently marked as obsolete, but only in the sense that we reserve the right to change their shape per feedback. Please be careful using these types as they may change in the future. At some point, we will remove the obsoletions and they will be considered stable APIs. See [here](../general/diagnosticids.md) for details. **Action needed**: If using `OpenXmlPackage.Package`, the package returned is no longer of type `System.IO.Packaging.Package`, but of `DocumentFormat.OpenXml.Packaging.IPackage`. @@ -92,7 +93,7 @@ In previous versions, [OpenXmlPartReader](/dotnet/api/documentformat.openxml.ope `SchemaAttrAttribute` and `ChildElementInfoAttribute` have been removed from types and the types themselves are no longer present. -**Action needed**: If these types were required, please engage us at https://github.com/dotnet/open-xml-sdk to figure out the best way forward for you. +**Action needed**: If these types were required, please engage us on [GitHub](https://github.com/dotnet/open-xml-sdk) to identify the best way forward for you. ### OpenXmlPackage.Close has been removed @@ -116,4 +117,4 @@ This property provided a dictionary that allowed access to change the extensions Previously, there was a heuristic to potentially minimize processing if no parts had been loaded. However, this caused scenarios such as ones where someone manually edited the XML to not actually process upon saving. v3.0.0 fixes this behavior and processes all part if this has been opted in. -**Action needed**: If you only want loaded parts to be processed, change to `MarkupCompatibilityProcessMode.ProcessLoadedPartsOnly` \ No newline at end of file +**Action needed**: If you only want loaded parts to be processed, change to `MarkupCompatibilityProcessMode.ProcessLoadedPartsOnly` diff --git a/docs/toc.yml b/docs/toc.yml index 690b49e3..871f7ce4 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -36,6 +36,8 @@ href: general/how-to-replace-the-theme-part-in-a-word-processing-document.md - name: Search and replace text in a document part href: general/how-to-search-and-replace-text-in-a-document-part.md + - name: Diagnostic IDs + href: general/diagnosticids.md - name: Presentations items: - name: Overview From bacf32132f12dcf9ebdbc291f9c01c978d002f0a Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Mon, 13 Nov 2023 15:34:22 -0800 Subject: [PATCH 4/8] Update --- docs/general/diagnosticids.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/general/diagnosticids.md b/docs/general/diagnosticids.md index 980dfe52..5aad7144 100644 --- a/docs/general/diagnosticids.md +++ b/docs/general/diagnosticids.md @@ -13,7 +13,11 @@ ms.localizationpriority: high Diagnostic IDs are used to identify APIs or patterns that can raise compiler warnings or errors. This can be done via [ObsoleteAttribute](/dotnet/api/system.obsoleteattribute.diagnosticid) or [ExperimentalAttribute](/dotnet/api/system.diagnostics.codeanalysis.experimentalattribute). These can be suppressed at the consumer level for each diagnostic id. -## OOXML0001 - IPackage related APIs are currently experimental +## Current obsolete or experimental APIs + +### OOXML0001 + +**Title**: IPackage related APIs are currently experimental As of v3.0, a new abstraction layer was added in between `System.IO.Packaging` and `DocumentFormat.OpenXml.Packaging.OpenXmlPackage`. This is currently experimental, but can be used if needed. This will be stabalized in a future release, and may or may not require code changes. From ab8afe328ad6bde5a15d72352a02562eb6eb6d9b Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Mon, 13 Nov 2023 15:39:32 -0800 Subject: [PATCH 5/8] Rename --- docs/general/diagnosticids.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/general/diagnosticids.md b/docs/general/diagnosticids.md index 5aad7144..bddef395 100644 --- a/docs/general/diagnosticids.md +++ b/docs/general/diagnosticids.md @@ -13,7 +13,7 @@ ms.localizationpriority: high Diagnostic IDs are used to identify APIs or patterns that can raise compiler warnings or errors. This can be done via [ObsoleteAttribute](/dotnet/api/system.obsoleteattribute.diagnosticid) or [ExperimentalAttribute](/dotnet/api/system.diagnostics.codeanalysis.experimentalattribute). These can be suppressed at the consumer level for each diagnostic id. -## Current obsolete or experimental APIs +## Experimental APIs ### OOXML0001 From eef7dcc3447a6d6480695cf7a6a56bab0aa8d0db Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Wed, 15 Nov 2023 11:16:56 -0800 Subject: [PATCH 6/8] add some examples --- docs/migration/migrate-v2-to-v3.md | 34 +++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/migration/migrate-v2-to-v3.md b/docs/migration/migrate-v2-to-v3.md index 0ff664ac..d808db11 100644 --- a/docs/migration/migrate-v2-to-v3.md +++ b/docs/migration/migrate-v2-to-v3.md @@ -71,11 +71,43 @@ Starting with v3.0.0, `EnumValue` wraps a custom type that contains the infor **Action needed**: Similar API surface is available, however the exposed enum values for this are no longer constants and will not be available in a few scenarios they had been (i.e. attribute values). +A common change that is required is switch statements no longer work: + +```csharp +switch (theCell.DataType.Value) +{ + case CellValues.SharedString: + // Handle the case + break; +} +``` + +becomes: + +```csharp +if (theCell.DataType.Value == CellValues.SharedString) +{ + // Handle the case +} +``` + ### OpenXmlElementList is now a struct [OpenXmlElementList](/dotnet/api/documentformat.openxml.openxmlelementlist) is now a struct. It still implements `IEnumerable` in addition to `IReadOnlyList` where available. -**Action needed**: None +**Action needed**: Because this is a struct, code patterns that may have a `null` result will now be a `OpenXmlElementList?` instead. Null checks will be flagged by the compiler and the value itself will need to be unwrapped, such as: + +```diff +- OpenXmlElementList? slideIds = part?.Presentation?.SlideIdList?.ChildElements; ++ OpenXmlElementList slideIds = part?.Presentation?.SlideIdList?.ChildElements ?? default; +``` + +or + +```diff +- OpenXmlElementList? slideIds = part?.Presentation?.SlideIdList?.ChildElements; ++ OpenXmlElementList slideIds = (part?.Presentation?.SlideIdList?.ChildElements).GetValueOrDefault(); +``` ### IdPartPair is now a readonly struct From 0b1ba55439df3143ca2cfca222b6e740116902cd Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Wed, 15 Nov 2023 11:19:01 -0800 Subject: [PATCH 7/8] more --- docs/migration/migrate-v2-to-v3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migration/migrate-v2-to-v3.md b/docs/migration/migrate-v2-to-v3.md index d808db11..4b42b2fb 100644 --- a/docs/migration/migrate-v2-to-v3.md +++ b/docs/migration/migrate-v2-to-v3.md @@ -113,7 +113,7 @@ or This type is used to enumerate pairs within a part and caused many unnecessary allocations. This change should be transparent upon recompilation. -**Action needed**: None +**Action needed**: Because this is now a struct, null handling code will need to be updated. ### OpenXmlPartReader no longer knows about all parts From 9b7ba896e076ef97891c39d0614b10156a115d36 Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Wed, 15 Nov 2023 11:21:24 -0800 Subject: [PATCH 8/8] add date --- docs/what-s-new-in-the-open-xml-sdk.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/what-s-new-in-the-open-xml-sdk.md b/docs/what-s-new-in-the-open-xml-sdk.md index 3b6b4b6e..fb72f390 100644 --- a/docs/what-s-new-in-the-open-xml-sdk.md +++ b/docs/what-s-new-in-the-open-xml-sdk.md @@ -17,7 +17,7 @@ ms.localizationpriority: high # What's new in the Open XML SDK -## [3.0.0] +## [3.0.0] - 2023-11-15 ### Added @@ -63,7 +63,7 @@ ms.localizationpriority: high - Removed `OpenXmlPackage.Close` in favor of `Dispose` (#1373) - Removed `OpenXmlPackage.SaveAs` in favor of `Clone` (#1376) -## [2.20.0] +## [2.20.0] - 2023-04-05 ### Added - Added DocumentFormat.OpenXml.Office.Drawing.Y2022.ImageFormula namespace