diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Template/TemplateControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Template/TemplateControllerBase.cs index d56b2cde2924..d0bc1db9250c 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Template/TemplateControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Template/TemplateControllerBase.cs @@ -38,6 +38,10 @@ protected IActionResult TemplateOperationStatusResult(TemplateOperationStatus st .WithTitle("Master template not found") .WithDetail("The master template referenced in the template was not found.") .Build()), + TemplateOperationStatus.MasterTemplateCannotBeDeleted => BadRequest(problemDetailsBuilder + .WithTitle("Master template cannot be deleted") + .WithDetail("The master templates cannot be deleted. Please ensure the template is not a master template before you delete.") + .Build()), _ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder .WithTitle("Unknown template operation status.") .Build()), diff --git a/src/Umbraco.Core/IO/ViewHelper.cs b/src/Umbraco.Core/IO/ViewHelper.cs index a02beaac0919..0e0ca72ed470 100644 --- a/src/Umbraco.Core/IO/ViewHelper.cs +++ b/src/Umbraco.Core/IO/ViewHelper.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Text; using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DependencyInjection; @@ -90,7 +91,7 @@ public string CreateView(ITemplate t, bool overWrite = false) return t.Content; } - public string ViewPath(string alias) => _viewFileSystem.GetRelativePath(alias.Replace(" ", string.Empty) + ".cshtml"); + public string ViewPath(string alias) => _viewFileSystem.GetRelativePath(CultureInfo.InvariantCulture.TextInfo.ToTitleCase(alias.Replace(" ", string.Empty)) + ".cshtml"); private string SaveTemplateToFile(ITemplate template) { diff --git a/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs index d7de5441e74f..80ccd78dd2ba 100644 --- a/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs @@ -8,5 +8,6 @@ public enum TemplateOperationStatus DuplicateAlias, TemplateNotFound, MasterTemplateNotFound, - CircularMasterTemplateReference + CircularMasterTemplateReference, + MasterTemplateCannotBeDeleted, } diff --git a/src/Umbraco.Core/Services/TemplateService.cs b/src/Umbraco.Core/Services/TemplateService.cs index 173b6d2d62c4..a3531f02e7d1 100644 --- a/src/Umbraco.Core/Services/TemplateService.cs +++ b/src/Umbraco.Core/Services/TemplateService.cs @@ -404,6 +404,12 @@ private void Audit(AuditType type, int userId, int objectId, string? entityType) return Attempt.FailWithStatus(TemplateOperationStatus.TemplateNotFound, null); } + if (template.IsMasterTemplate) + { + scope.Complete(); + return Attempt.FailWithStatus(TemplateOperationStatus.MasterTemplateCannotBeDeleted, null); + } + EventMessages eventMessages = EventMessagesFactory.Get(); var deletingNotification = new TemplateDeletingNotification(template, eventMessages); if (scope.Notifications.PublishCancelable(deletingNotification)) diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TemplateServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TemplateServiceTests.cs index 2c8e588b9c68..b5a5a42dcabb 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TemplateServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TemplateServiceTests.cs @@ -195,7 +195,7 @@ public async Task Can_Delete_Template() } [Test] - public async Task Deleting_Master_Template_Also_Deletes_Children() + public async Task Master_Template_Cannot_Be_Deleted() { Attempt result = await TemplateService.CreateAsync("Parent", "parent", "test", Constants.Security.SuperUserKey); Assert.IsTrue(result.Success); @@ -207,10 +207,8 @@ public async Task Deleting_Master_Template_Also_Deletes_Children() Assert.AreEqual("parent", child.MasterTemplateAlias); result = await TemplateService.DeleteAsync(parent.Key, Constants.Security.SuperUserKey); - Assert.IsTrue(result.Success); - - child = await TemplateService.GetAsync(child.Key); - Assert.Null(child); + Assert.IsFalse(result.Success); + Assert.That(result.Status, Is.EqualTo(TemplateOperationStatus.MasterTemplateCannotBeDeleted)); } [Test] diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index 6c4eafafb690..ff867ae253a1 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -6,7 +6,7 @@ Contains helper classes for integration tests with Umbraco CMS, including all internal integration tests. Umbraco.Cms.Tests.Integration true - $(BaseEnablePackageValidation) + false NU5100