V15: Fix webhook RTE serialization (#17656)
* Make base type resolver class * Add new webhook serializer * fix comment * Update src/Umbraco.Infrastructure/Serialization/ContentJsonTypeResolverBase.cs Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com> * Update src/Umbraco.Core/Services/WebhookRequestService.cs --------- Co-authored-by: Elitsa <elm@umbraco.dk> Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>
This commit is contained in:
@@ -1,56 +1,7 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using Umbraco.Cms.Core.Models.DeliveryApi;
|
||||
using Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Api.Delivery.Json;
|
||||
|
||||
// see https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0
|
||||
public class DeliveryApiJsonTypeResolver : DefaultJsonTypeInfoResolver
|
||||
{
|
||||
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
|
||||
{
|
||||
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
|
||||
|
||||
Type[] derivedTypes = GetDerivedTypes(jsonTypeInfo);
|
||||
if (derivedTypes.Length > 0)
|
||||
{
|
||||
ConfigureJsonPolymorphismOptions(jsonTypeInfo, derivedTypes);
|
||||
}
|
||||
|
||||
return jsonTypeInfo;
|
||||
}
|
||||
|
||||
protected virtual Type[] GetDerivedTypes(JsonTypeInfo jsonTypeInfo)
|
||||
{
|
||||
if (jsonTypeInfo.Type == typeof(IApiContent))
|
||||
{
|
||||
return new[] { typeof(ApiContent) };
|
||||
}
|
||||
|
||||
if (jsonTypeInfo.Type == typeof(IApiContentResponse))
|
||||
{
|
||||
return new[] { typeof(ApiContentResponse) };
|
||||
}
|
||||
|
||||
if (jsonTypeInfo.Type == typeof(IRichTextElement))
|
||||
{
|
||||
return new[] { typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement) };
|
||||
}
|
||||
|
||||
return Array.Empty<Type>();
|
||||
}
|
||||
|
||||
protected void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
|
||||
{
|
||||
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
|
||||
{
|
||||
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
|
||||
};
|
||||
|
||||
foreach (Type derivedType in derivedTypes)
|
||||
{
|
||||
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(new JsonDerivedType(derivedType));
|
||||
}
|
||||
}
|
||||
}
|
||||
public class DeliveryApiJsonTypeResolver : ContentJsonTypeResolverBase
|
||||
{ }
|
||||
|
||||
@@ -26,8 +26,6 @@ using Umbraco.Cms.Core.Notifications;
|
||||
using Umbraco.Cms.Core.Packaging;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Core.PublishedCache.Internal;
|
||||
using Umbraco.Cms.Core.Routing;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
@@ -37,6 +35,7 @@ using Umbraco.Cms.Core.Services.ContentTypeEditing;
|
||||
using Umbraco.Cms.Core.DynamicRoot;
|
||||
using Umbraco.Cms.Core.Preview;
|
||||
using Umbraco.Cms.Core.Security.Authorization;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services.FileSystem;
|
||||
using Umbraco.Cms.Core.Services.ImportExport;
|
||||
using Umbraco.Cms.Core.Services.Navigation;
|
||||
@@ -403,7 +402,10 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
Services.AddUnique<IWebhookService, WebhookService>();
|
||||
Services.AddUnique<IWebhookLogService, WebhookLogService>();
|
||||
Services.AddUnique<IWebhookLogFactory, WebhookLogFactory>();
|
||||
Services.AddUnique<IWebhookRequestService, WebhookRequestService>();
|
||||
Services.AddUnique<IWebhookRequestService>(factory => new WebhookRequestService(
|
||||
factory.GetRequiredService<ICoreScopeProvider>(),
|
||||
factory.GetRequiredService<IWebhookRequestRepository>(),
|
||||
factory.GetRequiredService<IWebhookJsonSerializer>()));
|
||||
|
||||
// Data type configuration cache
|
||||
Services.AddUnique<IDataTypeConfigurationCache, DataTypeConfigurationCache>();
|
||||
|
||||
4
src/Umbraco.Core/Serialization/IWebhookJsonSerializer.cs
Normal file
4
src/Umbraco.Core/Serialization/IWebhookJsonSerializer.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Umbraco.Cms.Core.Serialization;
|
||||
|
||||
public interface IWebhookJsonSerializer : IJsonSerializer
|
||||
{ }
|
||||
@@ -1,4 +1,6 @@
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
@@ -9,13 +11,19 @@ public class WebhookRequestService : IWebhookRequestService
|
||||
{
|
||||
private readonly ICoreScopeProvider _coreScopeProvider;
|
||||
private readonly IWebhookRequestRepository _webhookRequestRepository;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IWebhookJsonSerializer _webhookJsonSerializer;
|
||||
|
||||
[Obsolete("This constructor is obsolete and will be removed in future versions. Scheduled for removal in V17")]
|
||||
public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookRequestRepository webhookRequestRepository, IJsonSerializer jsonSerializer)
|
||||
: this (coreScopeProvider, webhookRequestRepository, StaticServiceProvider.Instance.GetRequiredService<IWebhookJsonSerializer>())
|
||||
{
|
||||
}
|
||||
|
||||
public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookRequestRepository webhookRequestRepository, IWebhookJsonSerializer webhookJsonSerializer)
|
||||
{
|
||||
_coreScopeProvider = coreScopeProvider;
|
||||
_webhookRequestRepository = webhookRequestRepository;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_webhookJsonSerializer = webhookJsonSerializer;
|
||||
}
|
||||
|
||||
public async Task<WebhookRequest> CreateAsync(Guid webhookKey, string eventAlias, object? payload)
|
||||
@@ -26,7 +34,7 @@ public class WebhookRequestService : IWebhookRequestService
|
||||
{
|
||||
WebhookKey = webhookKey,
|
||||
EventAlias = eventAlias,
|
||||
RequestObject = _jsonSerializer.Serialize(payload),
|
||||
RequestObject = _webhookJsonSerializer.Serialize(payload),
|
||||
RetryCount = 0,
|
||||
};
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ public static partial class UmbracoBuilderExtensions
|
||||
|
||||
builder.Services.AddSingleton<IJsonSerializer, SystemTextJsonSerializer>();
|
||||
builder.Services.AddSingleton<IConfigurationEditorJsonSerializer, SystemTextConfigurationEditorJsonSerializer>();
|
||||
builder.Services.AddUnique<IWebhookJsonSerializer, SystemTextWebhookJsonSerializer>();
|
||||
|
||||
// register database builder
|
||||
// *not* a singleton, don't want to keep it around
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using Umbraco.Cms.Core.Models.DeliveryApi;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
public abstract class ContentJsonTypeResolverBase : DefaultJsonTypeInfoResolver
|
||||
{
|
||||
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
|
||||
{
|
||||
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
|
||||
|
||||
Type[] derivedTypes = GetDerivedTypes(jsonTypeInfo);
|
||||
if (derivedTypes.Length > 0)
|
||||
{
|
||||
ConfigureJsonPolymorphismOptions(jsonTypeInfo, derivedTypes);
|
||||
}
|
||||
|
||||
return jsonTypeInfo;
|
||||
}
|
||||
|
||||
public virtual Type[] GetDerivedTypes(JsonTypeInfo jsonTypeInfo)
|
||||
{
|
||||
if (jsonTypeInfo.Type == typeof(IApiContent))
|
||||
{
|
||||
return new[] { typeof(ApiContent) };
|
||||
}
|
||||
|
||||
if (jsonTypeInfo.Type == typeof(IApiContentResponse))
|
||||
{
|
||||
return new[] { typeof(ApiContentResponse) };
|
||||
}
|
||||
|
||||
if (jsonTypeInfo.Type == typeof(IRichTextElement))
|
||||
{
|
||||
return new[] { typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement) };
|
||||
}
|
||||
|
||||
return Array.Empty<Type>();
|
||||
}
|
||||
|
||||
public void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
|
||||
{
|
||||
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
|
||||
{
|
||||
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
|
||||
};
|
||||
|
||||
foreach (Type derivedType in derivedTypes)
|
||||
{
|
||||
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(new JsonDerivedType(derivedType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed class SystemTextWebhookJsonSerializer : SystemTextJsonSerializerBase, IWebhookJsonSerializer
|
||||
{
|
||||
private readonly JsonSerializerOptions _jsonSerializerOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SystemTextWebhookJsonSerializer" /> class.
|
||||
/// </summary>
|
||||
public SystemTextWebhookJsonSerializer()
|
||||
=> _jsonSerializerOptions = new JsonSerializerOptions()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Converters =
|
||||
{
|
||||
new JsonStringEnumConverter(),
|
||||
new JsonUdiConverter(),
|
||||
new JsonUdiRangeConverter(),
|
||||
new JsonObjectConverter(), // Required for block editor values
|
||||
new JsonBlockValueConverter()
|
||||
},
|
||||
TypeInfoResolver = new WebhookJsonTypeResolver(),
|
||||
};
|
||||
|
||||
protected override JsonSerializerOptions JsonSerializerOptions => _jsonSerializerOptions;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
public class WebhookJsonTypeResolver : ContentJsonTypeResolverBase
|
||||
{ }
|
||||
Reference in New Issue
Block a user