From 5ab93454d9f06360c5fe405c9e2e022ed95320de Mon Sep 17 00:00:00 2001 From: Zeegaan Date: Fri, 28 Nov 2025 10:58:04 +0900 Subject: [PATCH 1/6] Bump version --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 17debcd846..a302632812 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json", - "version": "17.0.0", + "version": "17.0.1", "assemblyVersion": { "precision": "build" }, From e6b99938db307f76bb158425d8e2c60d6fa181e3 Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Date: Fri, 28 Nov 2025 16:25:06 +0900 Subject: [PATCH 2/6] Delivery API: Only add default strategy if delivery API is not registered. (#20982) * Only add if not already present * Update src/Umbraco.Cms.Api.Management/DependencyInjection/WebhooksBuilderExtensions.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Kenn Jacobsen --- .../DependencyInjection/WebhooksBuilderExtensions.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/WebhooksBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/WebhooksBuilderExtensions.cs index 81d764f697..fa3bcdb71a 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/WebhooksBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/WebhooksBuilderExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Umbraco.Cms.Api.Common.Accessors; using Umbraco.Cms.Api.Common.Rendering; using Umbraco.Cms.Api.Management.Factories; @@ -16,9 +16,10 @@ internal static class WebhooksBuilderExtensions builder.Services.AddUnique(); builder.AddMapDefinition(); - // deliveryApi will overwrite these more basic ones. - builder.Services.AddScoped(); - builder.Services.AddSingleton(); + // We have to use TryAdd here, as if they are registered by the delivery API, we don't want to register them + // Delivery API will also overwrite these IF it is enabled. + builder.Services.TryAddScoped(); + builder.Services.TryAddSingleton(); return builder; } From 1c4b4c90c9eeb884c307bc5898b6f7daacefa9bc Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 1 Dec 2025 12:52:35 +0100 Subject: [PATCH 3/6] Rendering: Don't use element cache level on snapshot cache level properties (#21006) Don't use element cache level on snapshot cache level propreties --- src/Umbraco.PublishedCache.HybridCache/PublishedProperty.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.PublishedCache.HybridCache/PublishedProperty.cs b/src/Umbraco.PublishedCache.HybridCache/PublishedProperty.cs index 0ba4b6873b..17f3716630 100644 --- a/src/Umbraco.PublishedCache.HybridCache/PublishedProperty.cs +++ b/src/Umbraco.PublishedCache.HybridCache/PublishedProperty.cs @@ -187,10 +187,10 @@ internal sealed class PublishedProperty : PublishedPropertyBase switch (cacheLevel) { case PropertyCacheLevel.None: + case PropertyCacheLevel.Snapshot: // Snapshot is obsolete, so for now treat as None // never cache anything cacheValues = new CacheValues(); break; - case PropertyCacheLevel.Snapshot: // Snapshot is obsolete, so for now treat as element case PropertyCacheLevel.Element: // cache within the property object itself, ie within the content object cacheValues = _cacheValues ??= new CacheValues(); From 75b40e79a2b46cd84b105e849bf804ce1ef27113 Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 26 Nov 2025 15:02:07 +0100 Subject: [PATCH 4/6] Cache: Add awaits to memory cache rebuilds to fix race conditions (#20960) * Await rebuilds and fix multiple open DataReaders * Add additional missing awaits (cherry picked from commit eaf5960a4dec09dd8a315942e06dd2b04956ff48) --- .../Cache/Refreshers/Implement/ContentCacheRefresher.cs | 4 ++-- .../Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs | 4 ++-- .../Cache/Refreshers/Implement/DataTypeCacheRefresher.cs | 2 +- .../Cache/Refreshers/Implement/MediaCacheRefresher.cs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs index 7505781ad9..c58e689a67 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs @@ -239,8 +239,8 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase documentTypeIds = payloads.Where(x => x.ItemType == nameof(IContentType)).Select(x => x.Id); IEnumerable mediaTypeIds = payloads.Where(x => x.ItemType == nameof(IMediaType)).Select(x => x.Id); - _documentCacheService.RebuildMemoryCacheByContentTypeAsync(documentTypeIds); - _mediaCacheService.RebuildMemoryCacheByContentTypeAsync(mediaTypeIds); + _documentCacheService.RebuildMemoryCacheByContentTypeAsync(documentTypeIds).GetAwaiter().GetResult(); + _mediaCacheService.RebuildMemoryCacheByContentTypeAsync(mediaTypeIds).GetAwaiter().GetResult(); }); // now we can trigger the event diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs index 101be3d0ac..dcc53e37f3 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs @@ -120,7 +120,7 @@ public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase mediaTypeIds = removedContentTypes .Where(x => x.ItemType == PublishedItemType.Media) .Select(x => x.Id); - _mediaCacheService.RebuildMemoryCacheByContentTypeAsync(mediaTypeIds); + _mediaCacheService.RebuildMemoryCacheByContentTypeAsync(mediaTypeIds).GetAwaiter().GetResult(); }); base.Refresh(payloads); } diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs index 45af4d2c8f..f54c78de1b 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs @@ -194,8 +194,8 @@ public sealed class MediaCacheRefresher : PayloadCacheRefresherBase Date: Mon, 1 Dec 2025 17:24:28 +0100 Subject: [PATCH 5/6] Delivery API: Missing Member Open API security scheme references (#21020) Use AddComponent for OpenAPI security scheme registration Fixes security requirements being serialized as empty objects in the OpenAPI document by using the document's AddComponent method instead of directly manipulating the SecuritySchemes dictionary. --- ...UmbracoMemberAuthenticationDeliveryApiSwaggerGenOptions.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Cms.Api.Delivery/Configuration/ConfigureUmbracoMemberAuthenticationDeliveryApiSwaggerGenOptions.cs b/src/Umbraco.Cms.Api.Delivery/Configuration/ConfigureUmbracoMemberAuthenticationDeliveryApiSwaggerGenOptions.cs index 5922768462..4ba3031a85 100644 --- a/src/Umbraco.Cms.Api.Delivery/Configuration/ConfigureUmbracoMemberAuthenticationDeliveryApiSwaggerGenOptions.cs +++ b/src/Umbraco.Cms.Api.Delivery/Configuration/ConfigureUmbracoMemberAuthenticationDeliveryApiSwaggerGenOptions.cs @@ -47,9 +47,7 @@ public class ConfigureUmbracoMemberAuthenticationDeliveryApiSwaggerGenOptions : return; } - swaggerDoc.Components ??= new OpenApiComponents(); - swaggerDoc.Components.SecuritySchemes ??= new Dictionary(); - swaggerDoc.Components.SecuritySchemes.Add( + swaggerDoc.AddComponent( AuthSchemeName, new OpenApiSecurityScheme { From 822a2fcf70ec34d7613bd7ad7f89c08ebacb94a2 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 1 Dec 2025 19:01:55 +0100 Subject: [PATCH 6/6] Migrations: Ensure `umbracoPropertyData` column casing (#21015) * Add migration to fix umbracoPropertyData column casing. * Improve migration with column existence check and logging - Add ILogger to log when column is renamed - Check if column exists with incorrect casing before renaming - Use fluent Rename API instead of raw SQL - Add XML remarks documentation ?? Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * Clarify what old and new column name really is --------- Co-authored-by: Claude Co-authored-by: kjac # Conflicts: # src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs --- .../Migrations/Upgrade/UmbracoPlan.cs | 3 ++ .../EnsureUmbracoPropertyDataColumnCasing.cs | 54 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_0_1/EnsureUmbracoPropertyDataColumnCasing.cs diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs index 599f8367e4..ac16a57ea7 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs @@ -140,5 +140,8 @@ public class UmbracoPlan : MigrationPlan To("26179D88-58CE-4C92-B4A4-3CBA6E7188AC"); To("{8B2C830A-4FFB-4433-8337-8649B0BF52C8}"); To("{1C38D589-26BB-4A46-9ABE-E4A0DF548A87}"); + + // To 17.0.1 + To("{BE5CA411-E12D-4455-A59E-F12A669E5363}"); } } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_0_1/EnsureUmbracoPropertyDataColumnCasing.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_0_1/EnsureUmbracoPropertyDataColumnCasing.cs new file mode 100644 index 0000000000..6c97c075dd --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_0_1/EnsureUmbracoPropertyDataColumnCasing.cs @@ -0,0 +1,54 @@ +using Microsoft.Extensions.Logging; +using NPoco; +using static Umbraco.Cms.Core.Constants; +using ColumnInfo = Umbraco.Cms.Infrastructure.Persistence.SqlSyntax.ColumnInfo; + +namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_17_0_1; + +/// +/// Ensures the propertyTypeId column in umbracoPropertyData has correct camel case naming. +/// +/// +/// SQL Server is case sensitive for columns used in a SQL Bulk insert statement (which is used in publishing +/// operations on umbracoPropertyData). +/// Earlier versions of Umbraco used all lower case for the propertyTypeId column name (propertytypeid), whereas newer versions +/// use camel case (propertyTypeId). +/// +public class EnsureUmbracoPropertyDataColumnCasing : AsyncMigrationBase +{ + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + public EnsureUmbracoPropertyDataColumnCasing(IMigrationContext context, ILogger logger) + : base(context) => _logger = logger; + + /// + protected override Task MigrateAsync() + { + // We only need to do this for SQL Server. + if (DatabaseType == DatabaseType.SQLite) + { + return Task.CompletedTask; + } + + const string oldColumnName = "propertytypeid"; + const string newColumnName = "propertyTypeId"; + ColumnInfo[] columns = [.. SqlSyntax.GetColumnsInSchema(Context.Database)]; + ColumnInfo? targetColumn = columns + .FirstOrDefault(x => x.TableName == DatabaseSchema.Tables.PropertyData && string.Equals(x.ColumnName, oldColumnName, StringComparison.InvariantCulture)); + if (targetColumn is not null) + { + // The column exists with incorrect casing, we need to rename it. + Rename.Column(oldColumnName) + .OnTable(DatabaseSchema.Tables.PropertyData) + .To(newColumnName) + .Do(); + + _logger.LogInformation("Renamed column {OldColumnName} to {NewColumnName} on table {TableName}", oldColumnName, newColumnName, DatabaseSchema.Tables.PropertyData); + } + + return Task.CompletedTask; + } +}