Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't configure JsonOptions by default #16837

Merged
merged 16 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -37,6 +39,7 @@ private static async Task<IResult> HandleAsync(
IContentDefinitionManager contentDefinitionManager,
IUpdateModelAccessor updateModelAccessor,
HttpContext httpContext,
IOptions<DocumentJsonSerializerOptions> options,
bool draft = false)
{
if (!await authorizationService.AuthorizeAsync(httpContext.User, CommonPermissions.AccessContentApi))
Expand Down Expand Up @@ -123,7 +126,7 @@ private static async Task<IResult> HandleAsync(
await contentManager.SaveDraftAsync(contentItem);
}

return TypedResults.Ok(contentItem);
return Results.Json(contentItem, options.Value.SerializerOptions);
Piedone marked this conversation as resolved.
Show resolved Hide resolved
}

private static void AddValidationErrorsToModelState(ContentValidateResult result, ModelStateDictionary modelState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,7 +25,8 @@ private static async Task<IResult> HandleAsync(
string contentItemId,
IContentManager contentManager,
IAuthorizationService authorizationService,
HttpContext httpContext)
HttpContext httpContext,
IOptions<DocumentJsonSerializerOptions> options)
{
if (!await authorizationService.AuthorizeAsync(httpContext.User, CommonPermissions.AccessContentApi))
{
Expand All @@ -44,6 +47,6 @@ private static async Task<IResult> HandleAsync(

await contentManager.RemoveAsync(contentItem);

return TypedResults.Ok(contentItem);
return Results.Json(contentItem, options.Value.SerializerOptions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,7 +25,8 @@ private static async Task<IResult> HandleAsync(
string contentItemId,
IContentManager contentManager,
IAuthorizationService authorizationService,
HttpContext httpContext)
HttpContext httpContext,
IOptions<DocumentJsonSerializerOptions> options)
{
if (!await authorizationService.AuthorizeAsync(httpContext.User, CommonPermissions.AccessContentApi))
{
Expand All @@ -42,6 +45,6 @@ private static async Task<IResult> HandleAsync(
return httpContext.ChallengeOrForbid("Api");
}

return TypedResults.Ok(contentItem);
return Results.Json(contentItem, options.Value.SerializerOptions);
Piedone marked this conversation as resolved.
Show resolved Hide resolved
}
}
2 changes: 2 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -59,6 +60,7 @@ public sealed class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddContentServices();
services.AddSingleton<IAnchorTag, ContentAnchorTag>();

services.Configure<LiquidViewOptions>(o =>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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<IConfigureOptions<MvcOptions>, MvcOptionsConfiguration>();

return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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)
=> typeof(IContent).IsAssignableFrom(type);
}
Original file line number Diff line number Diff line change
@@ -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<MvcOptions>
{
private readonly DocumentJsonSerializerOptions _documentOptions;

public MvcOptionsConfiguration(IOptions<DocumentJsonSerializerOptions> documentOptions)
{
_documentOptions = documentOptions.Value;
}

public void Configure(MvcOptions options)
{
options.OutputFormatters.Insert(0, new ContentSystemTextJsonOutputFormatter(_documentOptions.SerializerOptions));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Text.Json;
using Microsoft.AspNetCore.Mvc.Formatters;
using OrchardCore.Data.Documents;
using OrchardCore.Entities;

namespace OrchardCore.Json;

public sealed class DocumentSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter
{
public DocumentSystemTextJsonOutputFormatter(JsonSerializerOptions jsonSerializerOptions)
: base(jsonSerializerOptions)
{
}

protected override bool CanWriteType(Type type)
=> typeof(IDocument).IsAssignableFrom(type) ||
typeof(IEntity).IsAssignableFrom(type);
}
20 changes: 20 additions & 0 deletions src/OrchardCore/OrchardCore/Extensions/MvcOptionsConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using OrchardCore.Json;

namespace OrchardCore.Extensions;

internal sealed class MvcOptionsConfiguration : IConfigureOptions<MvcOptions>
{
private readonly DocumentJsonSerializerOptions _documentOptions;

public MvcOptionsConfiguration(IOptions<DocumentJsonSerializerOptions> documentOptions)
{
_documentOptions = documentOptions.Value;
}

public void Configure(MvcOptions options)
{
options.OutputFormatters.Insert(0, new DocumentSystemTextJsonOutputFormatter(_documentOptions.SerializerOptions));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -148,9 +149,8 @@ private static void AddDefaultServices(OrchardCoreBuilder builder)
services.AddScoped<ICalendarSelector, DefaultCalendarSelector>();

services.AddSingleton<IPoweredByMiddlewareOptions, PoweredByMiddlewareOptions>();

services.AddTransient<IConfigureOptions<Microsoft.AspNetCore.Http.Json.JsonOptions>, JsonOptionsConfigurations>();
services.AddTransient<IConfigureOptions<DocumentJsonSerializerOptions>, DocumentJsonSerializerOptionsConfiguration>();
services.AddTransient<IConfigureOptions<MvcOptions>, MvcOptionsConfiguration>();

services.AddScoped<IOrchardHelper, DefaultOrchardHelper>();
services.AddSingleton<IClientIPAddressAccessor, DefaultClientIPAddressAccessor>();
Expand Down
16 changes: 14 additions & 2 deletions src/docs/releases/2.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@

Release date: Not yet released

## Change Logs
Here's the updated version to include the reference to `IEntity` implementations:

## Change Log

### Behavioral Changes

#### `JsonOptions` Configuration

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<DocumentJsonSerializerOptions>` from the IoC container.
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved

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.
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved

### Users Feature

Expand Down Expand Up @@ -108,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).

Expand Down
Loading