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"