diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 760c0e2116..da4cdcfd19 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Reflection; using System.Runtime.Serialization; using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Strings; namespace Umbraco.Core.Models { @@ -173,7 +174,8 @@ namespace Umbraco.Core.Models { SetPropertyValueAndDetectChanges(o => { - _alias = value.ToSafeAlias(); + //_alias = value.ToSafeAlias(); + _alias = value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase); return _alias; }, _alias, AliasSelector); } diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 2168edba2f..f66a23d12c 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -4,6 +4,7 @@ using System.Runtime.Serialization; using System.Text.RegularExpressions; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.Mappers; +using Umbraco.Core.Strings; namespace Umbraco.Core.Models { @@ -94,7 +95,7 @@ namespace Umbraco.Core.Models { SetPropertyValueAndDetectChanges(o => { - _alias = value; + _alias = value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase); return _alias; }, _alias, AliasSelector); } diff --git a/src/Umbraco.Core/Strings/CleanStringType.cs b/src/Umbraco.Core/Strings/CleanStringType.cs index 4c53be4cb8..ea9603ec6f 100644 --- a/src/Umbraco.Core/Strings/CleanStringType.cs +++ b/src/Umbraco.Core/Strings/CleanStringType.cs @@ -57,8 +57,9 @@ namespace Umbraco.Core.Strings /// /// Umbraco "safe alias" case. /// - /// This is for backward compatibility. Casing is unchanged within terms, - /// and is pascal otherwise. + /// Uppercases the first char of each term except for the first + /// char of the string, everything else including the first char of the + /// string is unchanged. UmbracoCase = 0x20, diff --git a/src/Umbraco.Web/WebServices/CoreStringsController.cs b/src/Umbraco.Web/WebServices/CoreStringsController.cs index 2d8c8e71ce..087caa4e50 100644 --- a/src/Umbraco.Web/WebServices/CoreStringsController.cs +++ b/src/Umbraco.Web/WebServices/CoreStringsController.cs @@ -20,9 +20,11 @@ namespace Umbraco.Web.WebServices [HttpGet] public JsonResult ToSafeAlias(string value) { + // always return a proper camel-cased alias + // when checking... javascript does a case-unsensitive comparison return value == null ? Json(new {error = "no value."}, JsonRequestBehavior.AllowGet) - : Json(new { alias = value.ToSafeAlias() }, JsonRequestBehavior.AllowGet); + : Json(new { alias = value.ToCleanString(CleanStringType.Alias | CleanStringType.CamelCase) }, JsonRequestBehavior.AllowGet); } [HttpGet] diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs index 0e4b20c268..3bffc3bbdc 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs @@ -17,6 +17,7 @@ using ClientDependency.Core; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Strings; using Umbraco.Web.UI.Controls; using umbraco.BusinessLogic; using umbraco.cms.businesslogic; @@ -294,7 +295,7 @@ namespace umbraco.controls global::Umbraco.Web.UmbracoContext.Current = asyncState.UmbracoContext; _contentType.ContentTypeItem.Name = txtName.Text; - _contentType.ContentTypeItem.Alias = txtAlias.Text; + _contentType.ContentTypeItem.Alias = txtAlias.Text; // raw, contentType.Alias takes care of it _contentType.ContentTypeItem.Icon = ddlIcons.SelectedValue; _contentType.ContentTypeItem.Description = description.Text; _contentType.ContentTypeItem.Thumbnail = ddlThumbnails.SelectedValue; @@ -834,7 +835,9 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }}); GenericProperty gpData = gp.GenricPropertyControl; if (string.IsNullOrEmpty(gpData.Name.Trim()) == false && string.IsNullOrEmpty(gpData.Alias.Trim()) == false) { - var propertyTypeAlias = gpData.Alias.ToSafeAlias(); + // when creating a property don't do anything special, propertyType.Alias will take care of it + // don't enforce camel here because the user might have changed what the CoreStringsController returned + var propertyTypeAlias = gpData.Alias; if (contentTypeItem.PropertyTypeExists(propertyTypeAlias) == false) { //Find the DataTypeDefinition that the PropertyType should be based on @@ -891,7 +894,8 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }}); var propertyType = contentTypeItem.PropertyTypes.First(x => x.Alias == gpw.PropertyType.Alias); if (propertyType == null) continue; var dataTypeDefinition = ApplicationContext.Current.Services.DataTypeService.GetDataTypeDefinitionById(gpw.GenricPropertyControl.Type); - propertyType.Alias = gpw.GenricPropertyControl.Alias.ToSafeAlias(); + // when saving, respect user's casing, so do nothing here as propertyType takes care of it + propertyType.Alias = gpw.GenricPropertyControl.Alias; propertyType.Name = gpw.GenricPropertyControl.Name; propertyType.Description = gpw.GenricPropertyControl.Description; propertyType.ValidationRegExp = gpw.GenricPropertyControl.Validation; diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/nodetypeTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/nodetypeTasks.cs index d47ca194ba..fa721596f0 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/nodetypeTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/nodetypeTasks.cs @@ -5,6 +5,7 @@ using System.Web.Security; using Umbraco.Core; using Umbraco.Core.Models; using umbraco.BusinessLogic; +using Umbraco.Core.Strings; using umbraco.DataLayer; using umbraco.BasePages; using Umbraco.Core.IO; @@ -52,7 +53,9 @@ namespace umbraco ? new ContentType(-1) : new ContentType(ApplicationContext.Current.Services.ContentTypeService.GetContentType(parentId)); contentType.CreatorId = _userID; - contentType.Alias = Alias.Replace("'", "''"); + // when creating a content type, enforce PascalCase + // preserve separator because contentType.Alias will re-alias it + contentType.Alias = Alias.ToCleanString(CleanStringType.Alias | CleanStringType.PascalCase, ' '); contentType.Name = Alias.Replace("'", "''"); contentType.Icon = UmbracoSettings.IconPickerBehaviour == IconPickerBehaviour.HideFileDuplicates ? ".sprTreeFolder"