From 913b79d682cb6a733879f3cab51a9adfdd8c42ec Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Wed, 8 Oct 2025 07:56:49 +0200 Subject: [PATCH] Performance: Added request cache to media type retrieval in media picker validation (#20405) * Added request cache to media type retrieval in media picker validation. * Applied suggestions from code review. --- .../MediaPicker3PropertyEditor.cs | 26 +++++++++++++++---- ...ataValueReferenceFactoryCollectionTests.cs | 3 ++- .../MediaPicker3ValueEditorValidationTests.cs | 3 ++- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs index ae43c493ef..26efa02f10 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs @@ -82,7 +82,8 @@ public class MediaPicker3PropertyEditor : DataEditor IDataTypeConfigurationCache dataTypeReadCache, ILocalizedTextService localizedTextService, IMediaTypeService mediaTypeService, - IMediaNavigationQueryService mediaNavigationQueryService) + IMediaNavigationQueryService mediaNavigationQueryService, + AppCaches appCaches) : base(shortStringHelper, jsonSerializer, ioHelper, attribute) { _jsonSerializer = jsonSerializer; @@ -95,7 +96,7 @@ public class MediaPicker3PropertyEditor : DataEditor var validators = new TypedJsonValidatorRunner, MediaPicker3Configuration>( jsonSerializer, new MinMaxValidator(localizedTextService), - new AllowedTypeValidator(localizedTextService, mediaTypeService, _mediaService), + new AllowedTypeValidator(localizedTextService, mediaTypeService, _mediaService, appCaches), new StartNodeValidator(localizedTextService, mediaNavigationQueryService)); Validators.Add(validators); @@ -401,18 +402,22 @@ public class MediaPicker3PropertyEditor : DataEditor /// internal sealed class AllowedTypeValidator : ITypedJsonValidator, MediaPicker3Configuration> { + private const string MediaTypeCacheKeyFormat = nameof(AllowedTypeValidator) + "_MediaTypeKey_{0}"; + private readonly ILocalizedTextService _localizedTextService; private readonly IMediaTypeService _mediaTypeService; private readonly IMediaService _mediaService; + private readonly AppCaches _appCaches; /// /// Initializes a new instance of the class. /// - public AllowedTypeValidator(ILocalizedTextService localizedTextService, IMediaTypeService mediaTypeService, IMediaService mediaService) + public AllowedTypeValidator(ILocalizedTextService localizedTextService, IMediaTypeService mediaTypeService, IMediaService mediaService, AppCaches appCaches) { _localizedTextService = localizedTextService; _mediaTypeService = mediaTypeService; _mediaService = mediaService; + _appCaches = appCaches; } /// @@ -452,9 +457,20 @@ public class MediaPicker3PropertyEditor : DataEditor foreach (var typeAlias in distinctTypeAliases) { - IMediaType? type = _mediaTypeService.Get(typeAlias); + // Cache media type lookups since the same media type is likely to be used multiple times in validation, + // particularly if we have multiple languages and blocks. + var cacheKey = string.Format(MediaTypeCacheKeyFormat, typeAlias); + string? typeKey = _appCaches.RequestCache.GetCacheItem(cacheKey); + if (typeKey is null) + { + typeKey = _mediaTypeService.Get(typeAlias)?.Key.ToString(); + if (typeKey is not null) + { + _appCaches.RequestCache.Set(cacheKey, typeKey); + } + } - if (type is null || allowedTypes.Contains(type.Key.ToString()) is false) + if (typeKey is null || allowedTypes.Contains(typeKey) is false) { return [ diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs index 953301f74f..a5fed60fec 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs @@ -41,7 +41,8 @@ public class DataValueReferenceFactoryCollectionTests Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of())); + Mock.Of(), + AppCaches.Disabled)); private IIOHelper IOHelper { get; } = Mock.Of(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MediaPicker3ValueEditorValidationTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MediaPicker3ValueEditorValidationTests.cs index 6816b17615..8bd7f3b187 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MediaPicker3ValueEditorValidationTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MediaPicker3ValueEditorValidationTests.cs @@ -218,7 +218,8 @@ internal class MediaPicker3ValueEditorValidationTests Mock.Of(), Mock.Of(), mediaTypeServiceMock.Object, - mediaNavigationQueryServiceMock.Object) + mediaNavigationQueryServiceMock.Object, + AppCaches.Disabled) { ConfigurationObject = new MediaPicker3Configuration() };