Skip to content

Commit 82e58ea

Browse files
authored
V14: cherry pick #17656 (#17763)
* 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 <[email protected]> * Update src/Umbraco.Core/Services/WebhookRequestService.cs --------- Co-authored-by: Elitsa <[email protected]> Co-authored-by: Elitsa Marinovska <[email protected]> (cherry picked from commit 6f08178) * Add back missing usings
1 parent f048cfe commit 82e58ea

File tree

8 files changed

+117
-59
lines changed

8 files changed

+117
-59
lines changed
Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,7 @@
1-
using System.Text.Json;
2-
using System.Text.Json.Serialization;
3-
using System.Text.Json.Serialization.Metadata;
4-
using Umbraco.Cms.Core.Models.DeliveryApi;
1+
using Umbraco.Cms.Infrastructure.Serialization;
52

63
namespace Umbraco.Cms.Api.Delivery.Json;
74

85
// see https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0
9-
public class DeliveryApiJsonTypeResolver : DefaultJsonTypeInfoResolver
10-
{
11-
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
12-
{
13-
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
14-
15-
Type[] derivedTypes = GetDerivedTypes(jsonTypeInfo);
16-
if (derivedTypes.Length > 0)
17-
{
18-
ConfigureJsonPolymorphismOptions(jsonTypeInfo, derivedTypes);
19-
}
20-
21-
return jsonTypeInfo;
22-
}
23-
24-
protected virtual Type[] GetDerivedTypes(JsonTypeInfo jsonTypeInfo)
25-
{
26-
if (jsonTypeInfo.Type == typeof(IApiContent))
27-
{
28-
return new[] { typeof(ApiContent) };
29-
}
30-
31-
if (jsonTypeInfo.Type == typeof(IApiContentResponse))
32-
{
33-
return new[] { typeof(ApiContentResponse) };
34-
}
35-
36-
if (jsonTypeInfo.Type == typeof(IRichTextElement))
37-
{
38-
return new[] { typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement) };
39-
}
40-
41-
return Array.Empty<Type>();
42-
}
43-
44-
protected void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
45-
{
46-
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
47-
{
48-
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
49-
};
50-
51-
foreach (Type derivedType in derivedTypes)
52-
{
53-
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(new JsonDerivedType(derivedType));
54-
}
55-
}
56-
}
6+
public class DeliveryApiJsonTypeResolver : ContentJsonTypeResolverBase
7+
{ }

src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
using Umbraco.Cms.Core.Packaging;
2727
using Umbraco.Cms.Core.Persistence.Repositories;
2828
using Umbraco.Cms.Core.PropertyEditors;
29-
using Umbraco.Cms.Core.PublishedCache;
30-
using Umbraco.Cms.Core.PublishedCache.Internal;
3129
using Umbraco.Cms.Core.Routing;
3230
using Umbraco.Cms.Core.Runtime;
3331
using Umbraco.Cms.Core.Scoping;
@@ -36,7 +34,10 @@
3634
using Umbraco.Cms.Core.Services.ContentTypeEditing;
3735
using Umbraco.Cms.Core.DynamicRoot;
3836
using Umbraco.Cms.Core.Preview;
37+
using Umbraco.Cms.Core.PublishedCache;
38+
using Umbraco.Cms.Core.PublishedCache.Internal;
3939
using Umbraco.Cms.Core.Security.Authorization;
40+
using Umbraco.Cms.Core.Serialization;
4041
using Umbraco.Cms.Core.Services.FileSystem;
4142
using Umbraco.Cms.Core.Services.ImportExport;
4243
using Umbraco.Cms.Core.Services.Querying.RecycleBin;
@@ -373,7 +374,10 @@ private void AddCoreServices()
373374
Services.AddUnique<IWebhookService, WebhookService>();
374375
Services.AddUnique<IWebhookLogService, WebhookLogService>();
375376
Services.AddUnique<IWebhookLogFactory, WebhookLogFactory>();
376-
Services.AddUnique<IWebhookRequestService, WebhookRequestService>();
377+
Services.AddUnique<IWebhookRequestService>(factory => new WebhookRequestService(
378+
factory.GetRequiredService<ICoreScopeProvider>(),
379+
factory.GetRequiredService<IWebhookRequestRepository>(),
380+
factory.GetRequiredService<IWebhookJsonSerializer>()));
377381

378382
// Data type configuration cache
379383
Services.AddUnique<IDataTypeConfigurationCache, DataTypeConfigurationCache>();
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
namespace Umbraco.Cms.Core.Serialization;
2+
3+
public interface IWebhookJsonSerializer : IJsonSerializer
4+
{ }

src/Umbraco.Core/Services/WebhookRequestService.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Umbraco.Cms.Core.Models;
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Umbraco.Cms.Core.DependencyInjection;
3+
using Umbraco.Cms.Core.Models;
24
using Umbraco.Cms.Core.Persistence.Repositories;
35
using Umbraco.Cms.Core.Scoping;
46
using Umbraco.Cms.Core.Serialization;
@@ -9,13 +11,19 @@ public class WebhookRequestService : IWebhookRequestService
911
{
1012
private readonly ICoreScopeProvider _coreScopeProvider;
1113
private readonly IWebhookRequestRepository _webhookRequestRepository;
12-
private readonly IJsonSerializer _jsonSerializer;
14+
private readonly IWebhookJsonSerializer _webhookJsonSerializer;
1315

16+
[Obsolete("This constructor is obsolete and will be removed in future versions. Scheduled for removal in V17")]
1417
public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookRequestRepository webhookRequestRepository, IJsonSerializer jsonSerializer)
18+
: this (coreScopeProvider, webhookRequestRepository, StaticServiceProvider.Instance.GetRequiredService<IWebhookJsonSerializer>())
19+
{
20+
}
21+
22+
public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookRequestRepository webhookRequestRepository, IWebhookJsonSerializer webhookJsonSerializer)
1523
{
1624
_coreScopeProvider = coreScopeProvider;
1725
_webhookRequestRepository = webhookRequestRepository;
18-
_jsonSerializer = jsonSerializer;
26+
_webhookJsonSerializer = webhookJsonSerializer;
1927
}
2028

2129
public async Task<WebhookRequest> CreateAsync(Guid webhookKey, string eventAlias, object? payload)
@@ -26,7 +34,7 @@ public async Task<WebhookRequest> CreateAsync(Guid webhookKey, string eventAlias
2634
{
2735
WebhookKey = webhookKey,
2836
EventAlias = eventAlias,
29-
RequestObject = _jsonSerializer.Serialize(payload),
37+
RequestObject = _webhookJsonSerializer.Serialize(payload),
3038
RetryCount = 0,
3139
};
3240

src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builde
123123

124124
builder.Services.AddSingleton<IJsonSerializer, SystemTextJsonSerializer>();
125125
builder.Services.AddSingleton<IConfigurationEditorJsonSerializer, SystemTextConfigurationEditorJsonSerializer>();
126+
builder.Services.AddUnique<IWebhookJsonSerializer, SystemTextWebhookJsonSerializer>();
126127

127128
// register database builder
128129
// *not* a singleton, don't want to keep it around
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
using System.Text.Json.Serialization.Metadata;
4+
using Umbraco.Cms.Core.Models.DeliveryApi;
5+
6+
namespace Umbraco.Cms.Infrastructure.Serialization;
7+
8+
public abstract class ContentJsonTypeResolverBase : DefaultJsonTypeInfoResolver
9+
{
10+
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
11+
{
12+
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
13+
14+
Type[] derivedTypes = GetDerivedTypes(jsonTypeInfo);
15+
if (derivedTypes.Length > 0)
16+
{
17+
ConfigureJsonPolymorphismOptions(jsonTypeInfo, derivedTypes);
18+
}
19+
20+
return jsonTypeInfo;
21+
}
22+
23+
public virtual Type[] GetDerivedTypes(JsonTypeInfo jsonTypeInfo)
24+
{
25+
if (jsonTypeInfo.Type == typeof(IApiContent))
26+
{
27+
return new[] { typeof(ApiContent) };
28+
}
29+
30+
if (jsonTypeInfo.Type == typeof(IApiContentResponse))
31+
{
32+
return new[] { typeof(ApiContentResponse) };
33+
}
34+
35+
if (jsonTypeInfo.Type == typeof(IRichTextElement))
36+
{
37+
return new[] { typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement) };
38+
}
39+
40+
return Array.Empty<Type>();
41+
}
42+
43+
public void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
44+
{
45+
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
46+
{
47+
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
48+
};
49+
50+
foreach (Type derivedType in derivedTypes)
51+
{
52+
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(new JsonDerivedType(derivedType));
53+
}
54+
}
55+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
using Umbraco.Cms.Core.Serialization;
4+
5+
namespace Umbraco.Cms.Infrastructure.Serialization;
6+
7+
/// <inheritdoc />
8+
public sealed class SystemTextWebhookJsonSerializer : SystemTextJsonSerializerBase, IWebhookJsonSerializer
9+
{
10+
private readonly JsonSerializerOptions _jsonSerializerOptions;
11+
12+
/// <summary>
13+
/// Initializes a new instance of the <see cref="SystemTextWebhookJsonSerializer" /> class.
14+
/// </summary>
15+
public SystemTextWebhookJsonSerializer()
16+
=> _jsonSerializerOptions = new JsonSerializerOptions()
17+
{
18+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
19+
Converters =
20+
{
21+
new JsonStringEnumConverter(),
22+
new JsonUdiConverter(),
23+
new JsonUdiRangeConverter(),
24+
new JsonObjectConverter(), // Required for block editor values
25+
new JsonBlockValueConverter()
26+
},
27+
TypeInfoResolver = new WebhookJsonTypeResolver(),
28+
};
29+
30+
protected override JsonSerializerOptions JsonSerializerOptions => _jsonSerializerOptions;
31+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
namespace Umbraco.Cms.Infrastructure.Serialization;
2+
3+
public class WebhookJsonTypeResolver : ContentJsonTypeResolverBase
4+
{ }

0 commit comments

Comments
 (0)