From 35c0eb3d8334b03bd28643766c95fe336ddf10e5 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Fri, 4 Oct 2024 13:13:49 -0700 Subject: [PATCH 01/11] Don't configure JsonOptions by default --- .../Endpoints/Api/CreateEndpoint.cs | 5 ++++- .../Endpoints/Api/DeleteEndpoint.cs | 7 +++++-- .../Endpoints/Api/GetEndpoint.cs | 7 +++++-- .../Json/JsonOptionsConfigurations.cs | 21 ------------------- .../Extensions/ServiceCollectionExtensions.cs | 2 -- 5 files changed, 14 insertions(+), 28 deletions(-) delete mode 100644 src/OrchardCore/OrchardCore.Abstractions/Json/JsonOptionsConfigurations.cs diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/CreateEndpoint.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/CreateEndpoint.cs index d76cb805893..d89deb2329e 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/CreateEndpoint.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/CreateEndpoint.cs @@ -5,10 +5,12 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Options; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Handlers; using OrchardCore.ContentManagement.Metadata; using OrchardCore.DisplayManagement.ModelBinding; +using OrchardCore.Json; using OrchardCore.Modules; namespace OrchardCore.Contents.Endpoints.Api; @@ -37,6 +39,7 @@ private static async Task HandleAsync( IContentDefinitionManager contentDefinitionManager, IUpdateModelAccessor updateModelAccessor, HttpContext httpContext, + IOptions options, bool draft = false) { if (!await authorizationService.AuthorizeAsync(httpContext.User, CommonPermissions.AccessContentApi)) @@ -123,7 +126,7 @@ private static async Task HandleAsync( await contentManager.SaveDraftAsync(contentItem); } - return TypedResults.Ok(contentItem); + return Results.Json(contentItem, options.Value.SerializerOptions); } private static void AddValidationErrorsToModelState(ContentValidateResult result, ModelStateDictionary modelState) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/DeleteEndpoint.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/DeleteEndpoint.cs index c6b26c5e64e..677e725a607 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/DeleteEndpoint.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/DeleteEndpoint.cs @@ -2,7 +2,9 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Options; using OrchardCore.ContentManagement; +using OrchardCore.Json; using OrchardCore.Modules; namespace OrchardCore.Contents.Endpoints.Api; @@ -23,7 +25,8 @@ private static async Task HandleAsync( string contentItemId, IContentManager contentManager, IAuthorizationService authorizationService, - HttpContext httpContext) + HttpContext httpContext, + IOptions options) { if (!await authorizationService.AuthorizeAsync(httpContext.User, CommonPermissions.AccessContentApi)) { @@ -44,6 +47,6 @@ private static async Task HandleAsync( await contentManager.RemoveAsync(contentItem); - return TypedResults.Ok(contentItem); + return Results.Json(contentItem, options.Value.SerializerOptions); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/GetEndpoint.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/GetEndpoint.cs index 441f7d77ead..e3d7e870cbd 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/GetEndpoint.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Endpoints/Api/GetEndpoint.cs @@ -2,7 +2,9 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Options; using OrchardCore.ContentManagement; +using OrchardCore.Json; using OrchardCore.Modules; namespace OrchardCore.Contents.Endpoints.Api; @@ -23,7 +25,8 @@ private static async Task HandleAsync( string contentItemId, IContentManager contentManager, IAuthorizationService authorizationService, - HttpContext httpContext) + HttpContext httpContext, + IOptions options) { if (!await authorizationService.AuthorizeAsync(httpContext.User, CommonPermissions.AccessContentApi)) { @@ -42,6 +45,6 @@ private static async Task HandleAsync( return httpContext.ChallengeOrForbid("Api"); } - return TypedResults.Ok(contentItem); + return Results.Json(contentItem, options.Value.SerializerOptions); } } diff --git a/src/OrchardCore/OrchardCore.Abstractions/Json/JsonOptionsConfigurations.cs b/src/OrchardCore/OrchardCore.Abstractions/Json/JsonOptionsConfigurations.cs deleted file mode 100644 index 6fe32a8e641..00000000000 --- a/src/OrchardCore/OrchardCore.Abstractions/Json/JsonOptionsConfigurations.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Text.Json; -using Microsoft.AspNetCore.Http.Json; -using Microsoft.Extensions.Options; -using OrchardCore.Json.Extensions; - -namespace OrchardCore.Json; - -internal sealed class JsonOptionsConfigurations : IConfigureOptions -{ - private readonly JsonSerializerOptions _jsonSerializerOptions; - - public JsonOptionsConfigurations(IOptions jsonSerializerOptions) - { - _jsonSerializerOptions = jsonSerializerOptions.Value.SerializerOptions; - } - - public void Configure(JsonOptions options) - { - options.SerializerOptions.Merge(_jsonSerializerOptions); - } -} diff --git a/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs index a9d27667f9b..ea4c2bf621e 100644 --- a/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs +++ b/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs @@ -148,8 +148,6 @@ private static void AddDefaultServices(OrchardCoreBuilder builder) services.AddScoped(); services.AddSingleton(); - - services.AddTransient, JsonOptionsConfigurations>(); services.AddTransient, DocumentJsonSerializerOptionsConfiguration>(); services.AddScoped(); From 2e8d36ded59d2065fca7e141852cf61f94b0eb85 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Mon, 7 Oct 2024 07:41:49 -0700 Subject: [PATCH 02/11] update release notes --- src/docs/releases/2.1.0.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/docs/releases/2.1.0.md b/src/docs/releases/2.1.0.md index d9bd134801d..95d384718e1 100644 --- a/src/docs/releases/2.1.0.md +++ b/src/docs/releases/2.1.0.md @@ -4,6 +4,14 @@ Release date: Not yet released ## Change Logs +### Behavior Change + +#### `JsonOptions` Configuration + +One of the most significant changes in version 2.0 was the transition from Newtonsoft.Json to System.Text.Json. Initially, we configured the default `JsonOptions` to match the settings we used for serializing documents. However, in this release, we’ve reverted that decision and no longer configure `JsonOptions` by default, allowing you the flexibility to customize it as needed. + +If your API returns YesSql documents as JSON (e.g., ContentItem, User, Query, Notification), you may need to use `DocumentJsonSerializerOptions` for accurate serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(document)`, you should return it using `Results.Json(document, options.Value.SerializerOptions);`, resolving `IOptions` from the IoC container. + ### Users Feature #### External Authentication Logic Has Been Separated From the Users Feature From 3f1faf45cffac3f2449570ab2fe004ec56cdb2de Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 07:35:40 -0700 Subject: [PATCH 03/11] Adding output formatter --- .../DocumentSystemTextJsonOutputFormatter.cs | 20 +++++++++++++++++++ .../DocumentSystemTextJsonOutputFormatter.cs | 20 +++++++++++++++++++ .../Extensions/MvcOptionsConfiguration.cs | 20 +++++++++++++++++++ .../Extensions/ServiceCollectionExtensions.cs | 2 ++ 4 files changed, 62 insertions(+) create mode 100644 src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs create mode 100644 src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs create mode 100644 src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs diff --git a/src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs b/src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs new file mode 100644 index 00000000000..7a608c73c2f --- /dev/null +++ b/src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs @@ -0,0 +1,20 @@ +using System.Text.Json; +using Microsoft.AspNetCore.Mvc.Formatters; +using OrchardCore.Data.Documents; +using OrchardCore.Entities; + +namespace OrchardCore.Json; + +public class DocumentSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter +{ + public DocumentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerializerOptions) + : base(jsonSerializerOptions) + { + } + + protected override bool CanWriteType(Type type) + { + return typeof(IDocument).IsAssignableFrom(type) || + typeof(IEntity).IsAssignableFrom(type); + } +} diff --git a/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs b/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs new file mode 100644 index 00000000000..7a608c73c2f --- /dev/null +++ b/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs @@ -0,0 +1,20 @@ +using System.Text.Json; +using Microsoft.AspNetCore.Mvc.Formatters; +using OrchardCore.Data.Documents; +using OrchardCore.Entities; + +namespace OrchardCore.Json; + +public class DocumentSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter +{ + public DocumentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerializerOptions) + : base(jsonSerializerOptions) + { + } + + protected override bool CanWriteType(Type type) + { + return typeof(IDocument).IsAssignableFrom(type) || + typeof(IEntity).IsAssignableFrom(type); + } +} diff --git a/src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs b/src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs new file mode 100644 index 00000000000..7e3884122b0 --- /dev/null +++ b/src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using OrchardCore.Json; + +namespace OrchardCore.Extensions; + +public sealed class MvcOptionsConfiguration : IConfigureOptions +{ + private readonly DocumentJsonSerializerOptions _documentOptions; + + public MvcOptionsConfiguration(IOptions documentOptions) + { + _documentOptions = documentOptions.Value; + } + + public void Configure(MvcOptions options) + { + options.OutputFormatters.Insert(0, new DocumentSystemTextJsonOutputFormatter(_documentOptions.SerializerOptions)); + } +} diff --git a/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs index ea4c2bf621e..ac2a2e42ebe 100644 --- a/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs +++ b/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.DataProtection.XmlEncryption; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Localization; @@ -149,6 +150,7 @@ private static void AddDefaultServices(OrchardCoreBuilder builder) services.AddSingleton(); services.AddTransient, DocumentJsonSerializerOptionsConfiguration>(); + services.AddTransient, MvcOptionsConfiguration>(); services.AddScoped(); services.AddSingleton(); From 8c0638b8a8f90b742bf4db2e6c4aaad2aa7894aa Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 07:50:34 -0700 Subject: [PATCH 04/11] cleanup --- .../DocumentSystemTextJsonOutputFormatter.cs | 20 ------------------- .../DocumentSystemTextJsonOutputFormatter.cs | 2 +- .../Extensions/MvcOptionsConfiguration.cs | 2 +- src/docs/releases/2.1.0.md | 12 +++++++---- 4 files changed, 10 insertions(+), 26 deletions(-) delete mode 100644 src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs diff --git a/src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs b/src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs deleted file mode 100644 index 7a608c73c2f..00000000000 --- a/src/OrchardCore/OrchardCore.Infrastructure/DocumentSystemTextJsonOutputFormatter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Text.Json; -using Microsoft.AspNetCore.Mvc.Formatters; -using OrchardCore.Data.Documents; -using OrchardCore.Entities; - -namespace OrchardCore.Json; - -public class DocumentSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter -{ - public DocumentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerializerOptions) - : base(jsonSerializerOptions) - { - } - - protected override bool CanWriteType(Type type) - { - return typeof(IDocument).IsAssignableFrom(type) || - typeof(IEntity).IsAssignableFrom(type); - } -} diff --git a/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs b/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs index 7a608c73c2f..84d03c23cc9 100644 --- a/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs +++ b/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs @@ -5,7 +5,7 @@ namespace OrchardCore.Json; -public class DocumentSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter +public sealed class DocumentSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter { public DocumentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerializerOptions) : base(jsonSerializerOptions) diff --git a/src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs b/src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs index 7e3884122b0..c9360befd5e 100644 --- a/src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs +++ b/src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs @@ -4,7 +4,7 @@ namespace OrchardCore.Extensions; -public sealed class MvcOptionsConfiguration : IConfigureOptions +internal sealed class MvcOptionsConfiguration : IConfigureOptions { private readonly DocumentJsonSerializerOptions _documentOptions; diff --git a/src/docs/releases/2.1.0.md b/src/docs/releases/2.1.0.md index 95d384718e1..d85d2df2685 100644 --- a/src/docs/releases/2.1.0.md +++ b/src/docs/releases/2.1.0.md @@ -2,15 +2,19 @@ Release date: Not yet released -## Change Logs +Here's the updated version to include the reference to `IEntity` implementations: -### Behavior Change +## Change Log + +### Behavioral Changes #### `JsonOptions` Configuration -One of the most significant changes in version 2.0 was the transition from Newtonsoft.Json to System.Text.Json. Initially, we configured the default `JsonOptions` to match the settings we used for serializing documents. However, in this release, we’ve reverted that decision and no longer configure `JsonOptions` by default, allowing you the flexibility to customize it as needed. +A key change in version 2.0 is the shift from **Newtonsoft.Json** to **System.Text.Json**. Previously, we configured the default `JsonOptions` to match the settings used for document serialization. In this release, however, we’ve reverted that approach, and the `JsonOptions` are no longer configured by default. This change provides greater flexibility, allowing you to customize JSON serialization as needed. + +If your MinimalAPI returns YesSql documents or entities (implementations of `IEntity`), such as `ContentItem`, `User`, `Query`, or `Notification`, you may need to use `DocumentJsonSerializerOptions` for proper serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(entity)`, you should use `Results.Json(entity, options.Value.SerializerOptions)`, resolving `IOptions` from the IoC container. -If your API returns YesSql documents as JSON (e.g., ContentItem, User, Query, Notification), you may need to use `DocumentJsonSerializerOptions` for accurate serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(document)`, you should return it using `Results.Json(document, options.Value.SerializerOptions);`, resolving `IOptions` from the IoC container. +For scenarios using `ApiController` to return YesSql documents or entities, we’ve introduced a new output formatter, `DocumentSystemTextJsonOutputFormatter`, to automatically handle document serialization to JSON correctly. ### Users Feature From c52c8ac68c92fe54f477ff97ab091585a3865092 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 09:27:07 -0700 Subject: [PATCH 05/11] Add content formatter --- .../Startup.cs | 1 + .../OrchardCore.Contents/Startup.cs | 2 ++ .../ServiceCollectionExtensions.cs | 15 ++++++++++++++ .../ContentSystemTextJsonOutputFormatter.cs | 18 +++++++++++++++++ .../Services/MvcOptionsConfiguration.cs | 20 +++++++++++++++++++ src/docs/releases/2.1.0.md | 4 ++-- 6 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs create mode 100644 src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs create mode 100644 src/OrchardCore/OrchardCore.Contents.Core/Services/MvcOptionsConfiguration.cs diff --git a/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs index 5c66b843436..a52c502c3e7 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs @@ -12,6 +12,7 @@ using OrchardCore.ContentLocalization.Services; using OrchardCore.ContentLocalization.Sitemaps; using OrchardCore.ContentLocalization.ViewModels; +using OrchardCore.Contents.Core; using OrchardCore.Contents.Services; using OrchardCore.Contents.ViewModels; using OrchardCore.DisplayManagement.Handlers; diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs index 421776c1d26..c16e7fb6092 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs @@ -14,6 +14,7 @@ using OrchardCore.Contents.AdminNodes; using OrchardCore.Contents.AuditTrail.Settings; using OrchardCore.Contents.Controllers; +using OrchardCore.Contents.Core; using OrchardCore.Contents.Deployment; using OrchardCore.Contents.Drivers; using OrchardCore.Contents.Endpoints.Api; @@ -59,6 +60,7 @@ public sealed class Startup : StartupBase { public override void ConfigureServices(IServiceCollection services) { + services.AddContentServices(); services.AddSingleton(); services.Configure(o => diff --git a/src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs new file mode 100644 index 00000000000..11babf51f16 --- /dev/null +++ b/src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using OrchardCore.Contents.Core.Services; + +namespace OrchardCore.Contents.Core; +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddContentServices(this IServiceCollection services) + { + services.AddTransient, MvcOptionsConfiguration>(); + + return services; + } +} diff --git a/src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs b/src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs new file mode 100644 index 00000000000..6ef9bab2f02 --- /dev/null +++ b/src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs @@ -0,0 +1,18 @@ +using System.Text.Json; +using Microsoft.AspNetCore.Mvc.Formatters; +using OrchardCore.ContentManagement; + +namespace OrchardCore.Contents.Core.Services; + +public sealed class ContentSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter +{ + public ContentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerializerOptions) + : base(jsonSerializerOptions) + { + } + + protected override bool CanWriteType(Type type) + { + return typeof(IContent).IsAssignableFrom(type); + } +} diff --git a/src/OrchardCore/OrchardCore.Contents.Core/Services/MvcOptionsConfiguration.cs b/src/OrchardCore/OrchardCore.Contents.Core/Services/MvcOptionsConfiguration.cs new file mode 100644 index 00000000000..13d5b9fbd11 --- /dev/null +++ b/src/OrchardCore/OrchardCore.Contents.Core/Services/MvcOptionsConfiguration.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using OrchardCore.Json; + +namespace OrchardCore.Contents.Core.Services; + +internal sealed class MvcOptionsConfiguration : IConfigureOptions +{ + private readonly DocumentJsonSerializerOptions _documentOptions; + + public MvcOptionsConfiguration(IOptions documentOptions) + { + _documentOptions = documentOptions.Value; + } + + public void Configure(MvcOptions options) + { + options.OutputFormatters.Insert(0, new ContentSystemTextJsonOutputFormatter(_documentOptions.SerializerOptions)); + } +} diff --git a/src/docs/releases/2.1.0.md b/src/docs/releases/2.1.0.md index d85d2df2685..5cb71f168e9 100644 --- a/src/docs/releases/2.1.0.md +++ b/src/docs/releases/2.1.0.md @@ -12,9 +12,9 @@ Here's the updated version to include the reference to `IEntity` implementations A key change in version 2.0 is the shift from **Newtonsoft.Json** to **System.Text.Json**. Previously, we configured the default `JsonOptions` to match the settings used for document serialization. In this release, however, we’ve reverted that approach, and the `JsonOptions` are no longer configured by default. This change provides greater flexibility, allowing you to customize JSON serialization as needed. -If your MinimalAPI returns YesSql documents or entities (implementations of `IEntity`), such as `ContentItem`, `User`, `Query`, or `Notification`, you may need to use `DocumentJsonSerializerOptions` for proper serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(entity)`, you should use `Results.Json(entity, options.Value.SerializerOptions)`, resolving `IOptions` from the IoC container. +If your MinimalAPI returns YesSql documents, entities (implementations of `IEntity`) or content (implementations of `IContent`), such as `ContentItem`, `User`, `Query`, or `Notification`, you may need to use `DocumentJsonSerializerOptions` for proper serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(entity)`, you should use `Results.Json(entity, options.Value.SerializerOptions)`, resolving `IOptions` from the IoC container. -For scenarios using `ApiController` to return YesSql documents or entities, we’ve introduced a new output formatter, `DocumentSystemTextJsonOutputFormatter`, to automatically handle document serialization to JSON correctly. +For scenarios using `ApiController` to return YesSql documents or entities, we’ve introduced a new output formatters, `DocumentSystemTextJsonOutputFormatter` and `ContentSystemTextJsonOutputFormatter`, to automatically handle document serialization to JSON correctly. ### Users Feature From 6c6fa9bc4adb54a001fbab178d7ff4fcddffaa3a Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 09:35:50 -0700 Subject: [PATCH 06/11] new line --- .../OrchardCore.Contents.Core/ServiceCollectionExtensions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs index 11babf51f16..f2a0305bab5 100644 --- a/src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs +++ b/src/OrchardCore/OrchardCore.Contents.Core/ServiceCollectionExtensions.cs @@ -4,6 +4,7 @@ using OrchardCore.Contents.Core.Services; namespace OrchardCore.Contents.Core; + public static class ServiceCollectionExtensions { public static IServiceCollection AddContentServices(this IServiceCollection services) From de560d7672c1835f98601c167484e263adf08558 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 10:33:18 -0700 Subject: [PATCH 07/11] cleanup --- .../Services/ContentSystemTextJsonOutputFormatter.cs | 4 +--- .../Extensions/DocumentSystemTextJsonOutputFormatter.cs | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs b/src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs index 6ef9bab2f02..9979f0fdd21 100644 --- a/src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs +++ b/src/OrchardCore/OrchardCore.Contents.Core/Services/ContentSystemTextJsonOutputFormatter.cs @@ -12,7 +12,5 @@ public ContentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerializer } protected override bool CanWriteType(Type type) - { - return typeof(IContent).IsAssignableFrom(type); - } + => typeof(IContent).IsAssignableFrom(type); } diff --git a/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs b/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs index 84d03c23cc9..0bcc7b56a1a 100644 --- a/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs +++ b/src/OrchardCore/OrchardCore/Extensions/DocumentSystemTextJsonOutputFormatter.cs @@ -13,8 +13,6 @@ public DocumentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerialize } protected override bool CanWriteType(Type type) - { - return typeof(IDocument).IsAssignableFrom(type) || - typeof(IEntity).IsAssignableFrom(type); - } + => typeof(IDocument).IsAssignableFrom(type) || + typeof(IEntity).IsAssignableFrom(type); } From 60206f4167088fd4234be448c4c5766af5274017 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 12:35:08 -0700 Subject: [PATCH 08/11] fix leadlines --- src/docs/releases/2.1.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/releases/2.1.0.md b/src/docs/releases/2.1.0.md index 23431aa397f..46d41fb7740 100644 --- a/src/docs/releases/2.1.0.md +++ b/src/docs/releases/2.1.0.md @@ -120,7 +120,7 @@ Additionally, the configuration provider key for the default provider has change ### Autoroute Feature -### Content Item Shape Alternates Based on Alias and Slug +#### Content Item Shape Alternates Based on Alias and Slug Content item shapes can be overridden by their alias if `AliasPart` is attached or by their slug if `AutoroutePart` is attached. For examples, refer to the [docs](../reference/modules/Templates/README.md). From 930266bfeefbfbeaa56c42fc6fecddc3f0684fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Tue, 8 Oct 2024 22:05:01 +0200 Subject: [PATCH 09/11] Removing unnecessary namespace import --- .../OrchardCore.ContentLocalization/Startup.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs index a52c502c3e7..5c66b843436 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentLocalization/Startup.cs @@ -12,7 +12,6 @@ using OrchardCore.ContentLocalization.Services; using OrchardCore.ContentLocalization.Sitemaps; using OrchardCore.ContentLocalization.ViewModels; -using OrchardCore.Contents.Core; using OrchardCore.Contents.Services; using OrchardCore.Contents.ViewModels; using OrchardCore.DisplayManagement.Handlers; From 3c8fdb44a221d516a599b9474f4277bd1d1ba535 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 13:12:33 -0700 Subject: [PATCH 10/11] Update src/docs/releases/2.1.0.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Zoltán Lehóczky --- src/docs/releases/2.1.0.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/docs/releases/2.1.0.md b/src/docs/releases/2.1.0.md index 46d41fb7740..b4cee86a1ae 100644 --- a/src/docs/releases/2.1.0.md +++ b/src/docs/releases/2.1.0.md @@ -14,7 +14,9 @@ A key change in version 2.0 is the shift from **Newtonsoft.Json** to **System.Te If your MinimalAPI returns YesSql documents, entities (implementations of `IEntity`) or content (implementations of `IContent`), such as `ContentItem`, `User`, `Query`, or `Notification`, you may need to use `DocumentJsonSerializerOptions` for proper serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(entity)`, you should use `Results.Json(entity, options.Value.SerializerOptions)`, resolving `IOptions` from the IoC container. -For scenarios using `ApiController` to return YesSql documents or entities, we’ve introduced a new output formatters, `DocumentSystemTextJsonOutputFormatter` and `ContentSystemTextJsonOutputFormatter`, to automatically handle document serialization to JSON correctly. +For scenarios using `ApiController` to return YesSql documents or entities, we’ve introduced new output formatters, `DocumentSystemTextJsonOutputFormatter` and `ContentSystemTextJsonOutputFormatter`, to automatically handle document serialization to JSON correctly. + +These changes are non-breaking and you shouldn't need to change working 2.0.x code. ### Users Feature From 32b0bf6ff17096bfae08e98e12617c630d05d9b3 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 8 Oct 2024 13:12:45 -0700 Subject: [PATCH 11/11] Update src/docs/releases/2.1.0.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Zoltán Lehóczky --- src/docs/releases/2.1.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/releases/2.1.0.md b/src/docs/releases/2.1.0.md index b4cee86a1ae..be09e8884ce 100644 --- a/src/docs/releases/2.1.0.md +++ b/src/docs/releases/2.1.0.md @@ -12,7 +12,7 @@ Here's the updated version to include the reference to `IEntity` implementations A key change in version 2.0 is the shift from **Newtonsoft.Json** to **System.Text.Json**. Previously, we configured the default `JsonOptions` to match the settings used for document serialization. In this release, however, we’ve reverted that approach, and the `JsonOptions` are no longer configured by default. This change provides greater flexibility, allowing you to customize JSON serialization as needed. -If your MinimalAPI returns YesSql documents, entities (implementations of `IEntity`) or content (implementations of `IContent`), such as `ContentItem`, `User`, `Query`, or `Notification`, you may need to use `DocumentJsonSerializerOptions` for proper serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(entity)`, you should use `Results.Json(entity, options.Value.SerializerOptions)`, resolving `IOptions` from the IoC container. +If your Minimal API returns YesSql documents, entities (implementations of `IEntity`) or content (implementations of `IContent`), such as `ContentItem`, `User`, `Query`, or `Notification`, you may need to use `DocumentJsonSerializerOptions` for proper serialization. For example, when using Minimal API, instead of returning the result with `TypedResults.Ok(entity)`, you should use `Results.Json(entity, options.Value.SerializerOptions)`, resolving `IOptions` from the IoC container. For scenarios using `ApiController` to return YesSql documents or entities, we’ve introduced new output formatters, `DocumentSystemTextJsonOutputFormatter` and `ContentSystemTextJsonOutputFormatter`, to automatically handle document serialization to JSON correctly.