diff --git a/src/Umbraco.Core/Services/DictionaryItemService.cs b/src/Umbraco.Core/Services/DictionaryItemService.cs index 6b99ea7e24..809a482096 100644 --- a/src/Umbraco.Core/Services/DictionaryItemService.cs +++ b/src/Umbraco.Core/Services/DictionaryItemService.cs @@ -168,7 +168,9 @@ internal sealed class DictionaryItemService : RepositoryService, IDictionaryItem // So ensure we set something that can be distinguished here. if (dictionaryItem.CreateDate == default) { - dictionaryItem.CreateDate = DateTime.MinValue; + // Set such that it's prior to the update date, but not the default date which will be considered + // uninitialized and get reset to the current date at the repository. + dictionaryItem.CreateDate = DateTime.MinValue.AddHours(1); } if (dictionaryItem.UpdateDate == default) diff --git a/src/Umbraco.Core/Services/LanguageService.cs b/src/Umbraco.Core/Services/LanguageService.cs index 01a249dbd0..c815e490de 100644 --- a/src/Umbraco.Core/Services/LanguageService.cs +++ b/src/Umbraco.Core/Services/LanguageService.cs @@ -80,7 +80,27 @@ internal sealed class LanguageService : RepositoryService, ILanguageService /// public async Task> UpdateAsync(ILanguage language, Guid userKey) - => await SaveAsync( + { + // Create and update dates aren't tracked for languages. They exist on ILanguage due to the + // inheritance from IEntity, but we don't store them. + // However we have logic in ServerEventSender that will provide SignalR events for created and update operations, + // where these dates are used to distinguish between the two (whether or not the entity has an identity cannot + // be used here, as these events fire after persistence when the identity is known for both creates and updates). + // So ensure we set something that can be distinguished here. + if (language.CreateDate == default) + { + // Set such that it's prior to the update date, but not the default date which will be considered + // uninitialized and get reset to the current date at the repository. + language.CreateDate = DateTime.MinValue.AddHours(1); + } + + if (language.UpdateDate == default) + { + // TODO (V17): To align with updates of system dates, this needs to change to DateTime.UtcNow. + language.UpdateDate = DateTime.Now; + } + + return await SaveAsync( language, () => { @@ -101,6 +121,7 @@ internal sealed class LanguageService : RepositoryService, ILanguageService AuditType.Save, "Update Language", userKey); + } /// public async Task> CreateAsync(ILanguage language, Guid userKey) diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DictionaryItemServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DictionaryItemServiceTests.cs index e22ec36a5f..b32402872e 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DictionaryItemServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DictionaryItemServiceTests.cs @@ -362,6 +362,11 @@ internal sealed class DictionaryItemServiceTests : UmbracoIntegrationTest var result = await DictionaryItemService.UpdateAsync(item, Constants.Security.SuperUserKey); Assert.True(result.Success); + // Verify that the create and update dates can be used to distinguish between creates + // and updates (as these fields are used in ServerEventSender to emit a "Created" or "Updated" + // event. + Assert.Greater(result.Result.UpdateDate, result.Result.CreateDate); + var updatedItem = await DictionaryItemService.GetAsync("Child"); Assert.NotNull(updatedItem); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs index faf23ace24..9710512515 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs @@ -191,6 +191,11 @@ internal sealed class LanguageServiceTests : UmbracoIntegrationTest Assert.IsTrue(result.Success); Assert.AreEqual(LanguageOperationStatus.Success, result.Status); + // Verify that the create and update dates can be used to distinguish between creates + // and updates (as these fields are used in ServerEventSender to emit a "Created" or "Updated" + // event. + Assert.Greater(result.Result.UpdateDate, result.Result.CreateDate); + // re-get languageDaDk = await LanguageService.GetAsync(languageDaDk.IsoCode); Assert.NotNull(languageDaDk);