diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index dc093c8d20..c1d5bd35e3 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -211,73 +211,64 @@ namespace Umbraco.Core { { Comments, - new PropertyType(PropertyEditors.TextboxMultipleAlias, DataTypeDatabaseType.Ntext, true) + new PropertyType(PropertyEditors.TextboxMultipleAlias, DataTypeDatabaseType.Ntext, true, Comments) { - Alias = Comments, Name = CommentsLabel } }, { FailedPasswordAttempts, - new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Integer, true) + new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Integer, true, FailedPasswordAttempts) { - Alias = FailedPasswordAttempts, Name = FailedPasswordAttemptsLabel } }, { IsApproved, - new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, true) + new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, true, IsApproved) { - Alias = IsApproved, Name = IsApprovedLabel } }, { IsLockedOut, - new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, true) + new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, true, IsLockedOut) { - Alias = IsLockedOut, Name = IsLockedOutLabel } }, { LastLockoutDate, - new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true) + new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true, LastLockoutDate) { - Alias = LastLockoutDate, Name = LastLockoutDateLabel } }, { LastLoginDate, - new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true) + new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true, LastLoginDate) { - Alias = LastLoginDate, Name = LastLoginDateLabel } }, { LastPasswordChangeDate, - new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true) + new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true, LastPasswordChangeDate) { - Alias = LastPasswordChangeDate, Name = LastPasswordChangeDateLabel } }, { PasswordAnswer, - new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar, true) + new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar, true, PasswordAnswer) { - Alias = PasswordAnswer, Name = PasswordAnswerLabel } }, { PasswordQuestion, - new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar, true) + new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar, true, PasswordQuestion) { - Alias = PasswordQuestion, Name = PasswordQuestionLabel } } diff --git a/src/Umbraco.Core/Manifest/GridEditorConverter.cs b/src/Umbraco.Core/Manifest/GridEditorConverter.cs new file mode 100644 index 0000000000..76aaf4fc16 --- /dev/null +++ b/src/Umbraco.Core/Manifest/GridEditorConverter.cs @@ -0,0 +1,35 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Umbraco.Core.IO; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; + +namespace Umbraco.Core.Manifest +{ + /// + /// Ensures that virtual paths are taken care of + /// + internal class GridEditorConverter : JsonCreationConverter + { + protected override GridEditor Create(Type objectType, JObject jObject) + { + return new GridEditor(); + } + + protected override void Deserialize(JObject jObject, GridEditor target, JsonSerializer serializer) + { + base.Deserialize(jObject, target, serializer); + + if (target.View.IsNullOrWhiteSpace() == false && target.View.StartsWith("~/")) + { + target.View = IOHelper.ResolveUrl(target.View); + } + + if (target.Render.IsNullOrWhiteSpace() == false && target.Render.StartsWith("~/")) + { + target.Render = IOHelper.ResolveUrl(target.Render); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 7847eccf6e..aeb4da888c 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -39,7 +39,8 @@ namespace Umbraco.Core.Manifest internal static IEnumerable GetGridEditors(JArray jsonEditors) { return JsonConvert.DeserializeObject>( - jsonEditors.ToString()); + jsonEditors.ToString(), + new GridEditorConverter()); } /// @@ -209,14 +210,30 @@ namespace Umbraco.Core.Manifest } } } + + //replace virtual paths for each property editor + if (deserialized["gridEditors"] != null) + { + foreach (JObject p in deserialized["gridEditors"]) + { + if (p["view"] != null) + { + ReplaceVirtualPaths(p["view"]); + } + if (p["render"] != null) + { + ReplaceVirtualPaths(p["render"]); + } + } + } var manifest = new PackageManifest() { JavaScriptInitialize = jConfig, StylesheetInitialize = cssConfig, PropertyEditors = propEditors.Any() ? (JArray)deserialized["propertyEditors"] : new JArray(), - ParameterEditors = propEditors.Any() ? (JArray)deserialized["parameterEditors"] : new JArray(), - GridEditors = propEditors.Any() ? (JArray)deserialized["gridEditors"] : new JArray() + ParameterEditors = paramEditors.Any() ? (JArray)deserialized["parameterEditors"] : new JArray(), + GridEditors = gridEditors.Any() ? (JArray)deserialized["gridEditors"] : new JArray() }; result.Add(manifest); } diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index 0b29a90201..da9061fdc6 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -436,7 +436,7 @@ namespace Umbraco.Core.Models return; } - var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias); + var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); if (propertyType == null) { throw new Exception(String.Format("No PropertyType exists with the supplied alias: {0}", propertyTypeAlias)); diff --git a/src/Umbraco.Core/Models/EntityBase/Entity.cs b/src/Umbraco.Core/Models/EntityBase/Entity.cs index 0ecdee2b54..660d6674ca 100644 --- a/src/Umbraco.Core/Models/EntityBase/Entity.cs +++ b/src/Umbraco.Core/Models/EntityBase/Entity.cs @@ -17,7 +17,6 @@ namespace Umbraco.Core.Models.EntityBase public abstract class Entity : TracksChangesEntityBase, IEntity, IRememberBeingDirty, ICanBeDirty { private bool _hasIdentity; - private int? _hash; private int _id; private Guid _key; private DateTime _createDate; @@ -175,6 +174,7 @@ namespace Umbraco.Core.Models.EntityBase } } + //TODO: Make this NOT virtual or even exist really! public virtual bool SameIdentityAs(IEntity other) { if (ReferenceEquals(null, other)) @@ -195,11 +195,13 @@ namespace Umbraco.Core.Models.EntityBase return SameIdentityAs(other); } + //TODO: Make this NOT virtual or even exist really! public virtual Type GetRealType() { return GetType(); } + //TODO: Make this NOT virtual or even exist really! public virtual bool SameIdentityAs(Entity other) { if (ReferenceEquals(null, other)) @@ -226,9 +228,13 @@ namespace Umbraco.Core.Models.EntityBase public override int GetHashCode() { - if (!_hash.HasValue) - _hash = !HasIdentity ? new int?(base.GetHashCode()) : new int?(Id.GetHashCode() * 397 ^ GetType().GetHashCode()); - return _hash.Value; + unchecked + { + var hashCode = HasIdentity.GetHashCode(); + hashCode = (hashCode * 397) ^ Id; + hashCode = (hashCode * 397) ^ GetType().GetHashCode(); + return hashCode; + } } public virtual object DeepClone() diff --git a/src/Umbraco.Core/Models/PropertyCollection.cs b/src/Umbraco.Core/Models/PropertyCollection.cs index 0ff2e13484..67a6914739 100644 --- a/src/Umbraco.Core/Models/PropertyCollection.cs +++ b/src/Umbraco.Core/Models/PropertyCollection.cs @@ -16,12 +16,14 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class PropertyCollection : KeyedCollection, INotifyCollectionChanged, IDeepCloneable { - private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim(); + private readonly object _addLocker = new object(); internal Action OnAdd; internal Func ValidateAdd { get; set; } internal PropertyCollection() - {} + : base(StringComparer.InvariantCultureIgnoreCase) + { + } /// /// Initializes a new instance of the class with a delegate responsible for validating the addition of instances. @@ -29,11 +31,13 @@ namespace Umbraco.Core.Models /// The validation callback. /// internal PropertyCollection(Func validationCallback) + : this() { ValidateAdd = validationCallback; } public PropertyCollection(IEnumerable properties) + : this() { Reset(properties); } @@ -78,7 +82,7 @@ namespace Umbraco.Core.Models internal new void Add(Property item) { - using (new WriteLock(_addLocker)) + lock (_addLocker) { var key = GetKeyForItem(item); if (key != null) @@ -113,14 +117,14 @@ namespace Umbraco.Core.Models /// public new bool Contains(string propertyTypeAlias) { - return this.Any(x => x.Alias == propertyTypeAlias); + return base.Contains(propertyTypeAlias); } public int IndexOfKey(string key) { for (var i = 0; i < this.Count; i++) { - if (this[i].Alias == key) + if (this[i].Alias.InvariantEquals(key)) { return i; } @@ -145,7 +149,7 @@ namespace Umbraco.Core.Models { get { - return this.FirstOrDefault(x => x.Alias == propertyType.Alias); + return this.FirstOrDefault(x => x.Alias.InvariantEquals(propertyType.Alias)); } } @@ -165,7 +169,7 @@ namespace Umbraco.Core.Models /// List of PropertyType protected internal void EnsurePropertyTypes(IEnumerable propertyTypes) { - if(/*!this.Any() &&*/ propertyTypes != null) + if (/*!this.Any() &&*/ propertyTypes != null) { foreach (var propertyType in propertyTypes) { @@ -180,7 +184,7 @@ namespace Umbraco.Core.Models /// List of PropertyType protected internal void EnsureCleanPropertyTypes(IEnumerable propertyTypes) { - if(propertyTypes != null) + if (propertyTypes != null) { //Remove PropertyTypes that doesn't exist in the list of new PropertyTypes var aliases = this.Select(p => p.Alias).Except(propertyTypes.Select(x => x.Alias)).ToList(); diff --git a/src/Umbraco.Core/Models/PropertyGroup.cs b/src/Umbraco.Core/Models/PropertyGroup.cs index 35ddb6ac99..94e46e1ed1 100644 --- a/src/Umbraco.Core/Models/PropertyGroup.cs +++ b/src/Umbraco.Core/Models/PropertyGroup.cs @@ -120,27 +120,22 @@ namespace Umbraco.Core.Models public bool Equals(PropertyGroup other) { - //Check whether the compared object is null. - if (Object.ReferenceEquals(other, null)) return false; - - //Check whether the compared object references the same data. - if (Object.ReferenceEquals(this, other)) return true; + if (base.Equals(other)) return true; //Check whether the PropertyGroup's properties are equal. - return Id.Equals(other.Id) && Name.Equals(other.Name); + return Name.InvariantEquals(other.Name); } public override int GetHashCode() { - //Get hash code for the Name field if it is not null. - int hashName = Name == null ? 0 : Name.GetHashCode(); + int baseHash = base.GetHashCode(); - //Get hash code for the Id field. - int hashId = Id.GetHashCode(); + //Get hash code for the Alias field. + int nameHash = Name.ToLowerInvariant().GetHashCode(); //Calculate the hash code for the product. - return hashName ^ hashId; + return baseHash ^ nameHash; } } diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index d37465c44c..e9d4451314 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -38,11 +38,21 @@ namespace Umbraco.Core.Models _propertyEditorAlias = dataTypeDefinition.PropertyEditorAlias; _dataTypeDatabaseType = dataTypeDefinition.DatabaseType; } + + public PropertyType(IDataTypeDefinition dataTypeDefinition, string propertyTypeAlias) + : this(dataTypeDefinition) + { + SetAlias(propertyTypeAlias); + } - internal PropertyType(string propertyEditorAlias, DataTypeDatabaseType dataTypeDatabaseType) + public PropertyType(string propertyEditorAlias, DataTypeDatabaseType dataTypeDatabaseType) : this(propertyEditorAlias, dataTypeDatabaseType, false) { - PropertyEditorAlias = propertyEditorAlias; + } + + public PropertyType(string propertyEditorAlias, DataTypeDatabaseType dataTypeDatabaseType, string propertyTypeAlias) + : this(propertyEditorAlias, dataTypeDatabaseType, false, propertyTypeAlias) + { } /// @@ -58,6 +68,21 @@ namespace Umbraco.Core.Models _dataTypeDatabaseType = dataTypeDatabaseType; } + /// + /// Used internally to assign an explicity database type for this property type regardless of what the underlying data type/property editor is. + /// + /// + /// + /// + /// + internal PropertyType(string propertyEditorAlias, DataTypeDatabaseType dataTypeDatabaseType, bool isExplicitDbType, string propertyTypeAlias) + { + _isExplicitDbType = isExplicitDbType; + _propertyEditorAlias = propertyEditorAlias; + _dataTypeDatabaseType = dataTypeDatabaseType; + SetAlias(propertyTypeAlias); + } + private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias); private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo(x => x.Description); @@ -96,15 +121,9 @@ namespace Umbraco.Core.Models get { return _alias; } set { - //NOTE: WE are doing this because we don't want to do a ToSafeAlias when the alias is the special case of - // being prefixed with Constants.PropertyEditors.InternalGenericPropertiesPrefix - // which is used internally - SetPropertyValueAndDetectChanges(o => { - _alias = value.StartsWith(Constants.PropertyEditors.InternalGenericPropertiesPrefix) - ? value - : value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase); + SetAlias(value); return _alias; }, _alias, AliasSelector); } @@ -284,6 +303,17 @@ namespace Umbraco.Core.Models } } + private void SetAlias(string value) + { + //NOTE: WE are doing this because we don't want to do a ToSafeAlias when the alias is the special case of + // being prefixed with Constants.PropertyEditors.InternalGenericPropertiesPrefix + // which is used internally + + _alias = value.StartsWith(Constants.PropertyEditors.InternalGenericPropertiesPrefix) + ? value + : value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase); + } + /// /// Create a new Property object from a "raw" database value. /// @@ -431,26 +461,22 @@ namespace Umbraco.Core.Models public bool Equals(PropertyType other) { - //Check whether the compared object is null. - if (ReferenceEquals(other, null)) return false; - - //Check whether the compared object references the same data. - if (ReferenceEquals(this, other)) return true; + if (base.Equals(other)) return true; //Check whether the PropertyType's properties are equal. - return Alias.Equals(other.Alias) && Name.Equals(other.Name); + return Alias.InvariantEquals(other.Alias); } public override int GetHashCode() { //Get hash code for the Name field if it is not null. - int hashName = Name == null ? 0 : Name.GetHashCode(); + int baseHash = base.GetHashCode(); //Get hash code for the Alias field. - int hashAlias = Alias.GetHashCode(); + int hashAlias = Alias.ToLowerInvariant().GetHashCode(); //Calculate the hash code for the product. - return hashName ^ hashAlias; + return baseHash ^ hashAlias; } public override object DeepClone() diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs index a2c310d2bf..38ef4542f4 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs @@ -105,9 +105,9 @@ namespace Umbraco.Core.Persistence.Factories propDbType.Result, //This flag tells the property type that it has an explicit dbtype and that it cannot be changed // which is what we want for the built-in properties. - propDbType.Success) + propDbType.Success, + typeDto.Alias) { - Alias = typeDto.Alias, DataTypeDefinitionId = typeDto.DataTypeId, Description = typeDto.Description, Id = typeDto.Id.Value, @@ -157,9 +157,9 @@ namespace Umbraco.Core.Persistence.Factories propDbType.Result, //This flag tells the property type that it has an explicit dbtype and that it cannot be changed // which is what we want for the built-in properties. - propDbType.Success) + propDbType.Success, + typeDto.Alias) { - Alias = typeDto.Alias, DataTypeDefinitionId = typeDto.DataTypeId, Description = typeDto.Description, Id = typeDto.Id.Value, diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs index 3ae51c2edf..e35d474204 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs @@ -62,7 +62,7 @@ namespace Umbraco.Core.Persistence.Repositories protected virtual PropertyType CreatePropertyType(string propertyEditorAlias, DataTypeDatabaseType dbType, string propertyTypeAlias) { - return new PropertyType(propertyEditorAlias, dbType); + return new PropertyType(propertyEditorAlias, dbType, propertyTypeAlias); } protected void PersistNewBaseContentType(ContentTypeDto dto, IContentTypeComposition entity) @@ -447,8 +447,7 @@ AND umbracoNode.id <> @id", var list = new List(); foreach (var dto in dtos.Where(x => (x.PropertyTypeGroupId > 0) == false)) { - var propType = CreatePropertyType(dto.DataTypeDto.PropertyEditorAlias, dto.DataTypeDto.DbType.EnumParse(true), dto.Alias); - propType.Alias = dto.Alias; + var propType = CreatePropertyType(dto.DataTypeDto.PropertyEditorAlias, dto.DataTypeDto.DbType.EnumParse(true), dto.Alias); propType.DataTypeDefinitionId = dto.DataTypeId; propType.Description = dto.Description; propType.Id = dto.Id; @@ -1036,10 +1035,9 @@ AND umbracoNode.id <> @id", .Select(group => new PropertyGroup(new PropertyTypeCollection( result .Where(row => row.pgId == group.GroupId && row.ptId != null) - .Select(row => new PropertyType(row.dtPropEdAlias, Enum.Parse(row.dtDbType)) + .Select(row => new PropertyType(row.dtPropEdAlias, Enum.Parse(row.dtDbType), row.ptAlias) { //fill in the rest of the property type properties - Alias = row.ptAlias, Description = row.ptDesc, DataTypeDefinitionId = row.dtId, Id = row.ptId, @@ -1065,10 +1063,9 @@ AND umbracoNode.id <> @id", .Where(x => x.pgId == null) //filter based on the current content type .Where(x => x.contentTypeId == currId) - .Select(row => new PropertyType(row.dtPropEdAlias, Enum.Parse(row.dtDbType)) + .Select(row => new PropertyType(row.dtPropEdAlias, Enum.Parse(row.dtDbType), row.ptAlias) { //fill in the rest of the property type properties - Alias = row.ptAlias, Description = row.ptDesc, DataTypeDefinitionId = row.dtId, Id = row.ptId, diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs index fe47af4f20..bb6099a206 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs @@ -256,7 +256,8 @@ namespace Umbraco.Core.Persistence.Repositories return new PropertyType(propertyEditorAlias, propDbType.Result, //This flag tells the property type that it has an explicit dbtype and that it cannot be changed // which is what we want for the built-in properties. - propDbType.Success); + propDbType.Success, + propertyTypeAlias); } /// diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index 2bb1643b71..abc76a323c 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -1229,44 +1229,38 @@ namespace Umbraco.Core.Services Name = "Membership", Id = --identity }; - propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, Constants.Conventions.Member.Comments) { - Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Id = --identity }); - propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer) + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, Constants.Conventions.Member.IsApproved) { - Alias = Constants.Conventions.Member.IsApproved, Name = Constants.Conventions.Member.IsApprovedLabel, SortOrder = 3, Id = --identity }); - propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer) + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, Constants.Conventions.Member.IsLockedOut) { - Alias = Constants.Conventions.Member.IsLockedOut, Name = Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 4, Id = --identity }); - propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date) + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastLockoutDate) { - Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 5, Id = --identity }); - propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date) + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastLoginDate) { - Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 6, Id = --identity }); - propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date) + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastPasswordChangeDate) { - Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 7, Id = --identity diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index bb5a55de24..5b44cbb3e0 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -652,9 +652,8 @@ namespace Umbraco.Core.Services if (dataTypeDefinition == null) continue; } - var propertyType = new PropertyType(dataTypeDefinition) + var propertyType = new PropertyType(dataTypeDefinition, property.Element("Alias").Value) { - Alias = property.Element("Alias").Value, Name = property.Element("Name").Value, Description = property.Element("Description").Value, Mandatory = property.Element("Mandatory").Value.ToLowerInvariant().Equals("true"), diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7349020fef..69ef3fec88 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -345,6 +345,7 @@ + diff --git a/src/Umbraco.Core/XmlExtensions.cs b/src/Umbraco.Core/XmlExtensions.cs index 8784cbfb30..200b845002 100644 --- a/src/Umbraco.Core/XmlExtensions.cs +++ b/src/Umbraco.Core/XmlExtensions.cs @@ -38,7 +38,7 @@ namespace Umbraco.Core //NOTE: There are no nice methods to write it async, only flushing it async. We // could implement this ourselves but it'd be a very manual process. xdoc.WriteTo(xmlWriter); - await xmlWriter.FlushAsync(); + await xmlWriter.FlushAsync().ConfigureAwait(false); } } diff --git a/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs b/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs index 46e2212742..08dbd89fca 100644 --- a/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs +++ b/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs @@ -108,12 +108,11 @@ namespace Umbraco.Tests.CodeFirst.Definitions //Check if a PropertyType with the same alias already exists, as we don't want to override existing ones if(group.PropertyTypes.Contains(definition.Alias)) continue; - var propertyType = new PropertyType(definition.DataTypeDefinition) + var propertyType = new PropertyType(definition.DataTypeDefinition, definition.Alias) { Mandatory = definition.Mandatory, ValidationRegExp = definition.ValidationRegExp, SortOrder = definition.Order, - Alias = definition.Alias, Name = definition.Name }; diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 603ff56838..652f14d9e1 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -77,7 +77,7 @@ namespace Umbraco.Tests.Manifest alias: 'Test.Test2', name: 'Test 2', config: { key1: 'some default val' }, - view: '/hello/world.cshtml', + view: '~/hello/world.cshtml', icon: 'helloworld' }, { @@ -85,7 +85,7 @@ namespace Umbraco.Tests.Manifest name: 'Test 3', config: { key1: 'some default val' }, view: '/hello/world.html', - render: '/hello/world.cshtml', + render: '~/hello/world.cshtml', icon: 'helloworld' } ]"); @@ -314,6 +314,105 @@ namespace Umbraco.Tests.Manifest //} + [Test] + public void Create_Manifests_Editors() + { + var package1 = @"{ +propertyEditors: [], +javascript: ['~/test.js', '~/test2.js']}"; + + var package2 = "{css: ['~/style.css', '~/folder-name/sdsdsd/stylesheet.css']}"; + + var package3 = @"{ + 'javascript': [ ], + 'css': [ ], + 'gridEditors': [ + { + 'name': 'Small Hero', + 'alias': 'small-hero', + 'view': '/App_Plugins/MyPlugin/small-hero/editortemplate.html', + 'render': '/Views/Partials/Grid/Editors/SmallHero.cshtml', + 'icon': 'icon-presentation', + 'config': { + 'image': { + 'size': { + 'width': 1200, + 'height': 185 + } + }, + 'link': { + 'maxNumberOfItems': 1, + 'minNumberOfItems': 0 + } + } + }, + { + 'name': 'Document Links By Category', + 'alias': 'document-links-by-category', + 'view': '/App_Plugins/MyPlugin/document-links-by-category/editortemplate.html', + 'render': '/Views/Partials/Grid/Editors/DocumentLinksByCategory.cshtml', + 'icon': 'icon-umb-members' + } + ] +}"; + var package4 = @"{'propertyEditors': [ + { + alias: 'Test.Test1', + name: 'Test 1', + editor: { + view: '~/App_Plugins/MyPackage/PropertyEditors/MyEditor.html', + valueType: 'int', + validation: { + 'required': true, + 'Regex': '\\d*' + } + }, + prevalues: { + fields: [ + { + label: 'Some config 1', + key: 'key1', + view: '~/App_Plugins/MyPackage/PropertyEditors/Views/pre-val1.html', + validation: { + required: true + } + }, + { + label: 'Some config 2', + key: 'key2', + view: '~/App_Plugins/MyPackage/PropertyEditors/Views/pre-val2.html' + } + ] + } + } +]}"; + + var package5 = @"{'parameterEditors': [ + { + alias: 'parameter1', + name: 'My Parameter', + view: '~/App_Plugins/MyPackage/PropertyEditors/MyEditor.html' + }, + { + alias: 'parameter2', + name: 'Another parameter', + config: { key1: 'some config val' }, + view: '~/App_Plugins/MyPackage/PropertyEditors/CsvEditor.html' + } +]}"; + + var result = ManifestParser.CreateManifests(package1, package2, package3, package4, package5).ToArray(); + + var paramEditors = result.SelectMany(x => ManifestParser.GetParameterEditors(x.ParameterEditors)).ToArray(); + var propEditors = result.SelectMany(x => ManifestParser.GetPropertyEditors(x.PropertyEditors)).ToArray(); + var gridEditors = result.SelectMany(x => ManifestParser.GetGridEditors(x.GridEditors)).ToArray(); + + Assert.AreEqual(2, gridEditors.Count()); + Assert.AreEqual(2, paramEditors.Count()); + Assert.AreEqual(1, propEditors.Count()); + + } + [Test] public void Create_Manifest_With_Line_Comments() { diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs index f784dc3bea..49c7c4503b 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs @@ -46,14 +46,14 @@ namespace Umbraco.Tests.Migrations.Upgrades "tags1", "tags1", new PropertyTypeCollection(new[] { - new PropertyType("test", DataTypeDatabaseType.Ntext) {Alias = "tags1", Name = "tags1", SortOrder = 1, DataTypeDefinitionId = 1041}, + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags1") {Name = "tags1", SortOrder = 1, DataTypeDefinitionId = 1041}, })); var contentTypeWith2Tags = MockedContentTypes.CreateSimpleContentType( "tags2", "tags2", new PropertyTypeCollection(new[] { - new PropertyType("test", DataTypeDatabaseType.Ntext) {Alias = "tags1", Name = "tags1", SortOrder = 1, DataTypeDefinitionId = 1041}, - new PropertyType("test", DataTypeDatabaseType.Ntext) {Alias = "tags2", Name = "tags2", SortOrder = 1, DataTypeDefinitionId = 1041} + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags1") {Name = "tags1", SortOrder = 1, DataTypeDefinitionId = 1041}, + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags2") {Name = "tags2", SortOrder = 1, DataTypeDefinitionId = 1041} })); contentTypeRepository.AddOrUpdate(contentTypeWith1Tag); diff --git a/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs b/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs index d54e8727aa..eaaa36504b 100644 --- a/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs +++ b/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs @@ -11,6 +11,27 @@ namespace Umbraco.Tests.Models.Collections [TestFixture] public class PropertyCollectionTests : BaseUmbracoConfigurationTest { + [Test] + public void Property_Adds_Case_Insensitive_Compare() + { + var collection = new PropertyCollection(); + + collection.Add(new Property(new PropertyType("propEditor", DataTypeDatabaseType.Nvarchar, "test"))); + collection.Add(new Property(new PropertyType("propEditor", DataTypeDatabaseType.Nvarchar, "Test"))); + + Assert.AreEqual(1, collection.Count); + } + + [Test] + public void Property_Contains_Case_Insensitive_Compare() + { + var collection = new PropertyCollection(); + + collection.Add(new Property(new PropertyType("propEditor", DataTypeDatabaseType.Nvarchar, "test"))); + + Assert.IsTrue(collection.Contains("Test")); + } + [Test] public void SimpleOrder_Returns_Null_On_FirstOrDefault_When_Empty() { diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 12bc90ca2e..811d468cb1 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -65,8 +65,8 @@ namespace Umbraco.Tests.Models { var contentType = MockedContentTypes.CreateSimpleContentType(); //add non-grouped properties - contentType.AddPropertyType(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "nonGrouped1", Name = "Non Grouped 1", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); - contentType.AddPropertyType(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "nonGrouped2", Name = "Non Grouped 2", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + contentType.AddPropertyType(new PropertyType("test", DataTypeDatabaseType.Ntext, "nonGrouped1") { Name = "Non Grouped 1", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + contentType.AddPropertyType(new PropertyType("test", DataTypeDatabaseType.Ntext, "nonGrouped2") { Name = "Non Grouped 2", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); //ensure that nothing is marked as dirty contentType.ResetDirtyProperties(false); @@ -339,7 +339,7 @@ namespace Umbraco.Tests.Models var asDirty = (ICanBeDirty)clone; Assert.IsFalse(asDirty.IsPropertyDirty("Properties")); - clone.Properties.Add(new Property(1, Guid.NewGuid(), new PropertyType("test", DataTypeDatabaseType.Ntext) {Alias = "blah"}, "blah")); + clone.Properties.Add(new Property(1, Guid.NewGuid(), new PropertyType("test", DataTypeDatabaseType.Ntext, "blah"), "blah")); Assert.IsTrue(asDirty.IsPropertyDirty("Properties")); } @@ -478,9 +478,8 @@ namespace Umbraco.Tests.Models var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act - contentType.PropertyGroups["Content"].PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) + contentType.PropertyGroups["Content"].PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "Optional subtitle", Mandatory = false, @@ -501,9 +500,9 @@ namespace Umbraco.Tests.Models var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act - var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext) + var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "Optional subtitle", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 + Name = "Subtitle", Description = "Optional subtitle", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 }; contentType.PropertyGroups["Content"].PropertyTypes.Add(propertyType); content.Properties.Add(new Property(propertyType){Value = "This is a subtitle Test"}); @@ -521,9 +520,8 @@ namespace Umbraco.Tests.Models var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act - var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext) + var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "Optional subtitle", Mandatory = false, @@ -551,9 +549,9 @@ namespace Umbraco.Tests.Models var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act - note that the PropertyType's properties like SortOrder is not updated through the Content object - var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext) + var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "Title description added", Mandatory = false, SortOrder = 10, DataTypeDefinitionId = -88 + Name = "Title", Description = "Title description added", Mandatory = false, SortOrder = 10, DataTypeDefinitionId = -88 }; content.Properties.Add(new Property(propertyType)); @@ -739,9 +737,8 @@ namespace Umbraco.Tests.Models contentType.ResetDirtyProperties(); // Act - var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext) + var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "Optional subtitle", Mandatory = false, @@ -765,9 +762,8 @@ namespace Umbraco.Tests.Models new PropertyTypeCollection( new List { - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "coauthor") { - Alias = "coauthor", Name = "Co-Author", Description = "Name of the Co-Author", Mandatory = false, @@ -797,9 +793,8 @@ namespace Umbraco.Tests.Models new PropertyTypeCollection( new List { - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "coauthor") { - Alias = "coauthor", Name = "Co-Author", Description = "Name of the Co-Author", Mandatory = false, @@ -831,9 +826,8 @@ namespace Umbraco.Tests.Models var mixin1 = MockedContentTypes.CreateSimpleContentType("mixin1", "Mixin1", new PropertyTypeCollection( new List { - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "coauthor") { - Alias = "coauthor", Name = "Co-Author", Description = "Name of the Co-Author", Mandatory = false, @@ -844,9 +838,8 @@ namespace Umbraco.Tests.Models var mixin2 = MockedContentTypes.CreateSimpleContentType("mixin2", "Mixin2", new PropertyTypeCollection( new List { - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "Name of the Author", Mandatory = false, diff --git a/src/Umbraco.Tests/Models/ContentTypeTests.cs b/src/Umbraco.Tests/Models/ContentTypeTests.cs index 194dbc119b..325c8aefc1 100644 --- a/src/Umbraco.Tests/Models/ContentTypeTests.cs +++ b/src/Umbraco.Tests/Models/ContentTypeTests.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.Models } //add a property type without a property group contentType.PropertyTypeCollection.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "title2", Name = "Title2", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + new PropertyType("test", DataTypeDatabaseType.Ntext, "title2") { Name = "Title2", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); contentType.AllowedTemplates = new[] { new Template("-1,2", "Name", "name") { Id = 200 }, new Template("-1,3", "Name2", "name2") { Id = 201 } }; contentType.AllowedContentTypes = new[] { new ContentTypeSort(new Lazy(() => 888), 8, "sub"), new ContentTypeSort(new Lazy(() => 889), 9, "sub2") }; @@ -239,7 +239,7 @@ namespace Umbraco.Tests.Models var asDirty = (ICanBeDirty)clone; Assert.IsFalse(asDirty.IsPropertyDirty("PropertyTypes")); - clone.AddPropertyType(new PropertyType("test", DataTypeDatabaseType.Nvarchar) { Alias = "blah" }); + clone.AddPropertyType(new PropertyType("test", DataTypeDatabaseType.Nvarchar, "blah")); Assert.IsTrue(asDirty.IsPropertyDirty("PropertyTypes")); Assert.IsFalse(asDirty.IsPropertyDirty("PropertyGroups")); clone.AddPropertyGroup("hello"); diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs index 669a1ee5c7..a8c15e9a5e 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs @@ -132,8 +132,8 @@ namespace Umbraco.Tests.Models.Mapping var idSeed = 1; var contentType = MockedContentTypes.CreateSimpleContentType(); //add non-grouped properties - contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "nonGrouped1", Name = "Non Grouped 1", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); - contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "nonGrouped2", Name = "Non Grouped 2", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "nonGrouped1") { Name = "Non Grouped 1", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "nonGrouped2") { Name = "Non Grouped 2", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); //set ids or it wont work contentType.Id = idSeed; foreach (var p in contentType.PropertyTypes) diff --git a/src/Umbraco.Tests/Models/PropertyGroupTests.cs b/src/Umbraco.Tests/Models/PropertyGroupTests.cs index 413e94bfee..c5ae39be07 100644 --- a/src/Umbraco.Tests/Models/PropertyGroupTests.cs +++ b/src/Umbraco.Tests/Models/PropertyGroupTests.cs @@ -15,10 +15,9 @@ namespace Umbraco.Tests.Models var pg = new PropertyGroup( new PropertyTypeCollection(new[] { - new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar) + new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar, "test") { Id = 3, - Alias = "test", CreateDate = DateTime.Now, DataTypeDefinitionId = 5, PropertyEditorAlias = "propTest", @@ -32,10 +31,9 @@ namespace Umbraco.Tests.Models ValidationRegExp = "xxxx", DataTypeDatabaseType = DataTypeDatabaseType.Nvarchar }, - new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar) + new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar, "test2") { Id = 4, - Alias = "test2", CreateDate = DateTime.Now, DataTypeDefinitionId = 6, PropertyEditorAlias = "propTest", @@ -96,10 +94,9 @@ namespace Umbraco.Tests.Models var pg = new PropertyGroup( new PropertyTypeCollection(new[] { - new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar) + new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar, "test") { Id = 3, - Alias = "test", CreateDate = DateTime.Now, DataTypeDefinitionId = 5, PropertyEditorAlias = "propTest", @@ -113,10 +110,9 @@ namespace Umbraco.Tests.Models ValidationRegExp = "xxxx", DataTypeDatabaseType = DataTypeDatabaseType.Nvarchar }, - new PropertyType("TestPropertyEditor2", DataTypeDatabaseType.Nvarchar) + new PropertyType("TestPropertyEditor2", DataTypeDatabaseType.Nvarchar, "test2") { Id = 4, - Alias = "test2", CreateDate = DateTime.Now, DataTypeDefinitionId = 6, PropertyEditorAlias = "propTest", diff --git a/src/Umbraco.Tests/Models/PropertyTypeTests.cs b/src/Umbraco.Tests/Models/PropertyTypeTests.cs index e6a89a1717..96f28980ab 100644 --- a/src/Umbraco.Tests/Models/PropertyTypeTests.cs +++ b/src/Umbraco.Tests/Models/PropertyTypeTests.cs @@ -12,10 +12,9 @@ namespace Umbraco.Tests.Models [Test] public void Can_Deep_Clone() { - var pt = new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar) + var pt = new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar, "test") { Id = 3, - Alias = "test", CreateDate = DateTime.Now, DataTypeDefinitionId = 5, PropertyEditorAlias = "propTest", @@ -62,10 +61,9 @@ namespace Umbraco.Tests.Models { var ss = new SerializationService(new JsonNetSerializer()); - var pt = new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar) + var pt = new PropertyType("TestPropertyEditor", DataTypeDatabaseType.Nvarchar, "test") { Id = 3, - Alias = "test", CreateDate = DateTime.Now, DataTypeDefinitionId = 5, PropertyEditorAlias = "propTest", diff --git a/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs b/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs index 463657c4bd..4e4543ed40 100644 --- a/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs +++ b/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs @@ -176,9 +176,8 @@ namespace Umbraco.Tests.Persistence } contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory" + Guid.NewGuid().ToString("N"), "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 171cdbcf24..de7fed05bf 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -126,9 +126,8 @@ namespace Umbraco.Tests.Persistence.Repositories var contentType = repository.Get(NodeDto.NodeIdSeed + 1); contentType.Thumbnail = "Doc2.png"; - contentType.PropertyGroups["Content"].PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) + contentType.PropertyGroups["Content"].PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "Optional Subtitle", Mandatory = false, @@ -332,9 +331,8 @@ namespace Umbraco.Tests.Persistence.Repositories var contentType = repository.Get(NodeDto.NodeIdSeed + 1); // Act - var urlAlias = new PropertyType("test", DataTypeDatabaseType.Nvarchar) + var urlAlias = new PropertyType("test", DataTypeDatabaseType.Nvarchar, "urlAlias") { - Alias = "urlAlias", Name = "Url Alias", Description = "", Mandatory = false, @@ -434,7 +432,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta"); - propertyGroup.PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "metaAuthor", Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + propertyGroup.PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "metaAuthor") { Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); repository.AddOrUpdate(contentType); unitOfWork.Commit(); @@ -461,7 +459,7 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Commit(); var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta"); - propertyGroup.PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "metaAuthor", Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + propertyGroup.PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "metaAuthor") { Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); repository.AddOrUpdate(contentType); unitOfWork.Commit(); @@ -500,7 +498,7 @@ namespace Umbraco.Tests.Persistence.Repositories contentType.RemovePropertyType("keywords"); //Add PropertyType var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta"); - propertyGroup.PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "metaAuthor", Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + propertyGroup.PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "metaAuthor") { Name = "Meta Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); repository.AddOrUpdate(contentType); unitOfWork.Commit(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs index c69e7d0759..55a4b38ba4 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -70,9 +70,8 @@ namespace Umbraco.Tests.Persistence.Repositories var mediaType = repository.Get(NodeDto.NodeIdSeed); mediaType.Thumbnail = "Doc2.png"; - mediaType.PropertyGroups["Media"].PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) + mediaType.PropertyGroups["Media"].PropertyTypes.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "Optional Subtitle", Mandatory = false, diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 425da6ac2e..959ea9d615 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -78,9 +78,8 @@ namespace Umbraco.Tests.PublishedContent var mType = MockedContentTypes.CreateImageMediaType("image2"); //lets add an RTE to this mType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Nvarchar) + new PropertyType("test", DataTypeDatabaseType.Nvarchar, "content") { - Alias = "content", Name = "Rich Text", DataTypeDefinitionId = -87 //tiny mce }); diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index b6dfbd3584..f2f1e69983 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -6,6 +6,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; +using Umbraco.Web; using Umbraco.Web.Routing; using umbraco.cms.businesslogic.web; using System.Configuration; @@ -22,6 +23,12 @@ namespace Umbraco.Tests.Routing base.FreezeResolution(); } + { + SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper()); + + base.FreezeResolution(); + } + private void SetDomains1() { SetupDomainServiceMock(new[] @@ -326,6 +333,33 @@ namespace Umbraco.Tests.Routing Assert.AreEqual(pcr.PublishedContent.Id, expectedNode); } + #region Cases + [TestCase(10011, "http://domain1.com/", "en-US")] + [TestCase(100111, "http://domain1.com/", "en-US")] + [TestCase(10011, "http://domain1.fr/", "fr-FR")] + [TestCase(100111, "http://domain1.fr/", "fr-FR")] + [TestCase(1001121, "http://domain1.fr/", "de-DE")] + #endregion + public void GetCulture(int nodeId, string currentUrl, string expectedCulture) + { + var langEn = Language.GetByCultureCode("en-US"); + var langFr = Language.GetByCultureCode("fr-FR"); + var langDe = Language.GetByCultureCode("de-DE"); + + Domain.MakeNew("domain1.com/", 1001, langEn.id); + Domain.MakeNew("domain1.fr/", 1001, langFr.id); + Domain.MakeNew("*100112", 100112, langDe.id); + + var routingContext = GetRoutingContext("http://anything/"); + var umbracoContext = routingContext.UmbracoContext; + + var content = umbracoContext.ContentCache.GetById(nodeId); + Assert.IsNotNull(content); + + var culture = Web.Models.ContentExtensions.GetCulture(umbracoContext, null, null, content.Id, content.Path, new Uri(currentUrl)); + Assert.AreEqual(expectedCulture, culture.Name); + } + #region Cases [TestCase(10011, "http://domain1.com/", "en-US")] [TestCase(100111, "http://domain1.com/", "en-US")] diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs index f5b041fc9f..19f91d7ff2 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs @@ -6,27 +6,23 @@ using System.Threading; using System.Threading.Tasks; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Tests.TestHelpers; using Umbraco.Web.Scheduling; namespace Umbraco.Tests.Scheduling { [TestFixture] + [Timeout(30000)] public class BackgroundTaskRunnerTests { - private static void AssertRunnerStopsRunning(BackgroundTaskRunner runner, int timeoutMilliseconds = 2000) - where T : class, IBackgroundTask + [TestFixtureSetUp] + public void InitializeFixture() { - const int period = 200; - - var i = 0; - var m = timeoutMilliseconds/period; - while (runner.IsRunning && i++ < m) - Thread.Sleep(period); - Assert.IsFalse(runner.IsRunning, "Runner is still running."); + TestHelper.SetupLog4NetForTests(); } [Test] - public void ShutdownWaitWhenRunning() + public async void ShutdownWaitWhenRunning() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { AutoStart = true, KeepAlive = true })) { @@ -34,36 +30,41 @@ namespace Umbraco.Tests.Scheduling Thread.Sleep(800); // for long Assert.IsTrue(runner.IsRunning); runner.Shutdown(false, true); // -force +wait - AssertRunnerStopsRunning(runner); + await runner; // wait for the entire runner operation to complete Assert.IsTrue(runner.IsCompleted); } } [Test] - public void ShutdownWhenRunning() + public async void ShutdownWhenRunning() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { - // do NOT try to do this because the code must run on the UI thread which - // is not availably, and so the thread never actually starts - wondering - // what it means for ASP.NET? - //runner.TaskStarting += (sender, args) => Console.WriteLine("starting {0:c}", DateTime.Now); - //runner.TaskCompleted += (sender, args) => Console.WriteLine("completed {0:c}", DateTime.Now); + Console.WriteLine("Begin {0}", DateTime.Now); + + runner.TaskStarting += (sender, args) => Console.WriteLine("starting {0}", DateTime.Now); + runner.TaskCompleted += (sender, args) => Console.WriteLine("completed {0}", DateTime.Now); Assert.IsFalse(runner.IsRunning); + + Console.WriteLine("Adding task {0}", DateTime.Now); runner.Add(new MyTask(5000)); Assert.IsTrue(runner.IsRunning); // is running the task + Console.WriteLine("Shutting down {0}", DateTime.Now); runner.Shutdown(false, false); // -force -wait Assert.IsTrue(runner.IsCompleted); Assert.IsTrue(runner.IsRunning); // still running that task - Thread.Sleep(3000); + Thread.Sleep(3000); // wait slightly less than the task takes to complete Assert.IsTrue(runner.IsRunning); // still running that task - AssertRunnerStopsRunning(runner, 10000); + + await runner; // wait for the entire runner operation to complete + + Console.WriteLine("End {0}", DateTime.Now); } } [Test] - public void ShutdownFlushesTheQueue() + public async void ShutdownFlushesTheQueue() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -74,13 +75,13 @@ namespace Umbraco.Tests.Scheduling runner.Add(t); Assert.IsTrue(runner.IsRunning); // is running the first task runner.Shutdown(false, false); // -force -wait - AssertRunnerStopsRunning(runner, 10000); + await runner; // wait for the entire runner operation to complete Assert.AreNotEqual(DateTime.MinValue, t.Ended); // t has run } } [Test] - public void ShutdownForceTruncatesTheQueue() + public async void ShutdownForceTruncatesTheQueue() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -91,13 +92,13 @@ namespace Umbraco.Tests.Scheduling runner.Add(t); Assert.IsTrue(runner.IsRunning); // is running the first task runner.Shutdown(true, false); // +force -wait - AssertRunnerStopsRunning(runner, 10000); + await runner; // wait for the entire runner operation to complete Assert.AreEqual(DateTime.MinValue, t.Ended); // t has not run } } [Test] - public void ShutdownThenForce() + public async void ShutdownThenForce() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -112,7 +113,7 @@ namespace Umbraco.Tests.Scheduling Thread.Sleep(3000); Assert.IsTrue(runner.IsRunning); // still running that task runner.Shutdown(true, false); // +force -wait - AssertRunnerStopsRunning(runner, 20000); + await runner; // wait for the entire runner operation to complete } } @@ -126,12 +127,12 @@ namespace Umbraco.Tests.Scheduling } [Test] - public void Create_AutoStart_IsRunning() + public async void Create_AutoStart_IsRunning() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { AutoStart = true })) { Assert.IsTrue(runner.IsRunning); - AssertRunnerStopsRunning(runner); // though not for long + await runner; // wait for the entire runner operation to complete } } @@ -148,7 +149,7 @@ namespace Umbraco.Tests.Scheduling } [Test] - public void Dispose_IsRunning() + public async void Dispose_IsRunning() { BackgroundTaskRunner runner; using (runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { AutoStart = true, KeepAlive = true })) @@ -157,22 +158,10 @@ namespace Umbraco.Tests.Scheduling // dispose will stop it } - AssertRunnerStopsRunning(runner); + await runner; // wait for the entire runner operation to complete Assert.Throws(() => runner.Add(new MyTask())); } - - [Test] - public void Startup_IsRunning() - { - using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) - { - Assert.IsFalse(runner.IsRunning); - runner.StartUp(); - Assert.IsTrue(runner.IsRunning); - AssertRunnerStopsRunning(runner); // though not for long - } - } - + [Test] public void Startup_KeepAlive_IsRunning() { @@ -186,13 +175,19 @@ namespace Umbraco.Tests.Scheduling } [Test] - public void Create_AddTask_IsRunning() + public async void Create_AddTask_IsRunning() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { + var waitHandle = new ManualResetEvent(false); + runner.TaskCompleted += (sender, args) => + { + waitHandle.Set(); + }; runner.Add(new MyTask()); Assert.IsTrue(runner.IsRunning); - Thread.Sleep(800); // task takes 500ms + waitHandle.WaitOne(); + await runner; //since we are not being kept alive, it will quit Assert.IsFalse(runner.IsRunning); } } @@ -202,11 +197,16 @@ namespace Umbraco.Tests.Scheduling { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true })) { + var waitHandle = new ManualResetEvent(false); + runner.TaskCompleted += (sender, args) => + { + Assert.IsTrue(sender.IsRunning); + waitHandle.Set(); + }; runner.Add(new MyTask()); + waitHandle.WaitOne(); + Thread.Sleep(1000); // we are waiting a second just to prove that it's still running and hasn't been shut off Assert.IsTrue(runner.IsRunning); - Thread.Sleep(800); // task takes 500ms - Assert.IsTrue(runner.IsRunning); - // dispose will stop it } } @@ -218,9 +218,9 @@ namespace Umbraco.Tests.Scheduling var task = new MyTask(); Assert.IsTrue(task.Ended == default(DateTime)); runner.Add(task); - await runner; // wait 'til it's not running anymore + await runner.CurrentThreadingTask; // wait for the Task operation to complete Assert.IsTrue(task.Ended != default(DateTime)); // task is done - AssertRunnerStopsRunning(runner); // though not for long + await runner; // wait for the entire runner operation to complete } } @@ -235,19 +235,19 @@ namespace Umbraco.Tests.Scheduling { tasks.ForEach(runner.Add); - await runner; // wait 'til it's not running anymore + await runner; // wait for the entire runner operation to complete // check that tasks are done Assert.IsTrue(tasks.All(x => x.Ended != default(DateTime))); - Assert.AreEqual(TaskStatus.RanToCompletion, runner.TaskStatus); + Assert.AreEqual(TaskStatus.RanToCompletion, runner.CurrentThreadingTask.Status); Assert.IsFalse(runner.IsRunning); Assert.IsFalse(runner.IsDisposed); } } [Test] - public void WaitOnTask() + public async void WaitOnTask() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -258,12 +258,12 @@ namespace Umbraco.Tests.Scheduling runner.Add(task); waitHandle.WaitOne(); // wait 'til task is done Assert.IsTrue(task.Ended != default(DateTime)); // task is done - AssertRunnerStopsRunning(runner); // though not for long + await runner; // wait for the entire runner operation to complete } } [Test] - public void WaitOnTasks() + public async void WaitOnTasks() { var tasks = new Dictionary(); for (var i = 0; i < 10; i++) @@ -278,7 +278,7 @@ namespace Umbraco.Tests.Scheduling WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray()); Assert.IsTrue(tasks.All(x => x.Key.Ended != default(DateTime))); - AssertRunnerStopsRunning(runner); // though not for long + await runner; // wait for the entire runner operation to complete } } @@ -349,9 +349,9 @@ namespace Umbraco.Tests.Scheduling tasks.ForEach(tManager.Add); //wait till the thread is done - await tManager; + await tManager.CurrentThreadingTask; - Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus); + Assert.AreEqual(TaskStatus.RanToCompletion, tManager.CurrentThreadingTask.Status); Assert.IsFalse(tManager.IsRunning); Assert.IsFalse(tManager.IsDisposed); @@ -367,14 +367,14 @@ namespace Umbraco.Tests.Scheduling tasks.ForEach(tManager.Add); //wait till the thread is done - await tManager; + await tManager.CurrentThreadingTask; foreach (var task in tasks) { Assert.IsTrue(task.Ended != default(DateTime)); } - Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus); + Assert.AreEqual(TaskStatus.RanToCompletion, tManager.CurrentThreadingTask.Status); Assert.IsFalse(tManager.IsRunning); Assert.IsFalse(tManager.IsDisposed); } @@ -383,31 +383,39 @@ namespace Umbraco.Tests.Scheduling [Test] public void RecurringTaskTest() { - // note: can have BackgroundTaskRunner and use it in MyRecurringTask ctor - // because that ctor wants IBackgroundTaskRunner and the generic type - // parameter is contravariant ie defined as IBackgroundTaskRunner so doing the - // following is legal: - // var IBackgroundTaskRunner b = ...; - // var IBackgroundTaskRunner d = b; // legal - + var runCount = 0; + var waitHandle = new ManualResetEvent(false); using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { + runner.TaskCompleted += (sender, args) => runCount++; + runner.TaskStarting += async (sender, args) => + { + //wait for each task to finish once it's started + await sender.CurrentThreadingTask; + if (runCount > 3) + { + waitHandle.Set(); + } + }; + var task = new MyRecurringTask(runner, 200, 500); - MyRecurringTask.RunCount = 0; + runner.Add(task); - Thread.Sleep(5000); - Assert.GreaterOrEqual(MyRecurringTask.RunCount, 2); // keeps running, count >= 2 + + Assert.IsTrue(runner.IsRunning); // waiting on delay + Assert.AreEqual(0, runCount); + + waitHandle.WaitOne(); + + Assert.GreaterOrEqual(runCount, 4); // stops recurring runner.Shutdown(false, false); - AssertRunnerStopsRunning(runner); - - // timer may try to add a task but it won't work because runner is completed } } [Test] - public void DelayedTaskRuns() + public async void DelayedTaskRuns() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -418,14 +426,14 @@ namespace Umbraco.Tests.Scheduling Assert.IsTrue(runner.IsRunning); // still waiting for the task to release Assert.IsFalse(task.HasRun); task.Release(); - Thread.Sleep(500); + await runner.CurrentThreadingTask; //wait for current task to complete Assert.IsTrue(task.HasRun); - AssertRunnerStopsRunning(runner); // runs task & exit + await runner; // wait for the entire runner operation to complete } } [Test] - public void DelayedTaskStops() + public async void DelayedTaskStops() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -436,7 +444,7 @@ namespace Umbraco.Tests.Scheduling Assert.IsTrue(runner.IsRunning); // still waiting for the task to release Assert.IsFalse(task.HasRun); runner.Shutdown(false, false); - AssertRunnerStopsRunning(runner); // runs task & exit + await runner; // wait for the entire runner operation to complete Assert.IsTrue(task.HasRun); } } @@ -444,29 +452,36 @@ namespace Umbraco.Tests.Scheduling [Test] public void DelayedRecurring() { + var runCount = 0; + var waitHandle = new ManualResetEvent(false); using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { + runner.TaskCompleted += (sender, args) => runCount++; + runner.TaskStarting += async (sender, args) => + { + //wait for each task to finish once it's started + await sender.CurrentThreadingTask; + if (runCount > 3) + { + waitHandle.Set(); + } + }; + var task = new MyDelayedRecurringTask(runner, 2000, 1000); - MyDelayedRecurringTask.RunCount = 0; runner.Add(task); - Thread.Sleep(1000); Assert.IsTrue(runner.IsRunning); // waiting on delay - Assert.AreEqual(0, MyDelayedRecurringTask.RunCount); - Thread.Sleep(1200); - Assert.AreEqual(1, MyDelayedRecurringTask.RunCount); - Thread.Sleep(5000); - Assert.GreaterOrEqual(MyDelayedRecurringTask.RunCount, 2); // keeps running, count >= 2 + Assert.AreEqual(0, runCount); + + waitHandle.WaitOne(); + Assert.GreaterOrEqual(runCount, 4); // stops recurring runner.Shutdown(false, false); - AssertRunnerStopsRunning(runner); - - // timer may try to add a task but it won't work because runner is completed } } [Test] - public void FailingTaskSync() + public async void FailingTaskSync() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -476,14 +491,14 @@ namespace Umbraco.Tests.Scheduling var task = new MyFailingTask(false); // -async runner.Add(task); Assert.IsTrue(runner.IsRunning); - AssertRunnerStopsRunning(runner); // runs task & exit + await runner; // wait for the entire runner operation to complete Assert.AreEqual(1, exceptions.Count); // traced and reported } } [Test] - public void FailingTaskAsync() + public async void FailingTaskAsync() { using (var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions())) { @@ -493,7 +508,7 @@ namespace Umbraco.Tests.Scheduling var task = new MyFailingTask(true); // +async runner.Add(task); Assert.IsTrue(runner.IsRunning); - AssertRunnerStopsRunning(runner); // runs task & exit + await runner; // wait for the entire runner operation to complete Assert.AreEqual(1, exceptions.Count); // traced and reported } @@ -540,8 +555,6 @@ namespace Umbraco.Tests.Scheduling : base(source) { } - public static int RunCount { get; set; } - public override bool IsAsync { get { return false; } @@ -550,7 +563,6 @@ namespace Umbraco.Tests.Scheduling public override void PerformRun() { // nothing to do at the moment - RunCount += 1; } public override Task PerformRunAsync() @@ -621,7 +633,6 @@ namespace Umbraco.Tests.Scheduling { private readonly int _runMilliseconds; - public static int RunCount { get; set; } public MyRecurringTask(IBackgroundTaskRunner runner, int runMilliseconds, int periodMilliseconds) : base(runner, periodMilliseconds) @@ -636,8 +647,7 @@ namespace Umbraco.Tests.Scheduling } public override void PerformRun() - { - RunCount += 1; + { Thread.Sleep(_runMilliseconds); } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index b87d024aa8..f53f3f2293 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -128,9 +128,8 @@ namespace Umbraco.Tests.Services var tagService = ServiceContext.TagService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -165,9 +164,8 @@ namespace Umbraco.Tests.Services var tagService = ServiceContext.TagService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -199,9 +197,8 @@ namespace Umbraco.Tests.Services var tagService = ServiceContext.TagService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -233,9 +230,8 @@ namespace Umbraco.Tests.Services var tagService = ServiceContext.TagService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -270,9 +266,8 @@ namespace Umbraco.Tests.Services var tagService = ServiceContext.TagService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -315,9 +310,8 @@ namespace Umbraco.Tests.Services }); var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -362,9 +356,8 @@ namespace Umbraco.Tests.Services var contentTypeService = ServiceContext.ContentTypeService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -394,9 +387,8 @@ namespace Umbraco.Tests.Services var contentTypeService = ServiceContext.ContentTypeService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -424,9 +416,8 @@ namespace Umbraco.Tests.Services var contentTypeService = ServiceContext.ContentTypeService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); @@ -454,9 +445,8 @@ namespace Umbraco.Tests.Services var contentTypeService = ServiceContext.ContentTypeService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index fa623b4a28..7408429fa4 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -173,10 +173,9 @@ namespace Umbraco.Tests.Services var cts = ServiceContext.ContentTypeService; var dtdYesNo = ServiceContext.DataTypeService.GetDataTypeDefinitionById(-49); var ctBase = new ContentType(-1) { Name = "Base", Alias = "Base", Icon = "folder.gif", Thumbnail = "folder.png" }; - ctBase.AddPropertyType(new PropertyType(dtdYesNo) + ctBase.AddPropertyType(new PropertyType(dtdYesNo, Constants.Conventions.Content.NaviHide) { Name = "Hide From Navigation", - Alias = Constants.Conventions.Content.NaviHide } /*,"Navigation"*/); cts.Save(ctBase); @@ -190,7 +189,7 @@ namespace Umbraco.Tests.Services Thumbnail = "folder.png", AllowedAsRoot = true }; - ctHomePage.AddPropertyType(new PropertyType(dtdYesNo) { Name = "Some property", Alias = "someProperty" } + ctHomePage.AddPropertyType(new PropertyType(dtdYesNo, "someProperty") { Name = "Some property" } /*,"Navigation"*/); cts.Save(ctHomePage); @@ -222,9 +221,9 @@ namespace Umbraco.Tests.Services Trashed = false }; - contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", Mandatory = false, DataTypeDefinitionId = -88 }); - contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, DataTypeDefinitionId = -87 }); - contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "author", Name = "Author", Description = "Name of the author", Mandatory = false, DataTypeDefinitionId = -88 }); + contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { Name = "Title", Description = "", Mandatory = false, DataTypeDefinitionId = -88 }); + contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext, "bodyText") { Name = "Body Text", Description = "", Mandatory = false, DataTypeDefinitionId = -87 }); + contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { Name = "Author", Description = "Name of the author", Mandatory = false, DataTypeDefinitionId = -88 }); service.Save(contentType); @@ -488,9 +487,9 @@ namespace Umbraco.Tests.Services service.Save(child); // Act - var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var added = composition.AddPropertyType(duplicatePropertyType, "Meta"); @@ -524,9 +523,9 @@ namespace Umbraco.Tests.Services service.Save(advancedPage); // Act - var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var addedToBasePage = basePage.AddPropertyType(duplicatePropertyType, "Content"); var addedToAdvancedPage = advancedPage.AddPropertyType(duplicatePropertyType, "Content"); @@ -578,16 +577,16 @@ namespace Umbraco.Tests.Services service.Save(contentMetaComposition); // Act - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content"); service.Save(basePage); - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content"); service.Save(contentPage); @@ -596,9 +595,9 @@ namespace Umbraco.Tests.Services service.Save(advancedPage); //NOTE: It should not be possible to Save 'BasePage' with the Title PropertyType added - var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content"); @@ -643,30 +642,30 @@ namespace Umbraco.Tests.Services service.Save(metaComposition); // Act - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content"); service.Save(basePage); - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content"); service.Save(contentPage); - var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content"); service.Save(advancedPage); - var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content"); service.Save(seoComposition); @@ -723,30 +722,30 @@ namespace Umbraco.Tests.Services service.Save(metaComposition); // Act - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content"); service.Save(basePage); - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content"); service.Save(contentPage); - var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content"); service.Save(advancedPage); - var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content"); service.Save(seoComposition); @@ -763,10 +762,10 @@ namespace Umbraco.Tests.Services Assert.That(titleAdded, Is.True); Assert.That(seoCompositionAdded, Is.True); Assert.That(metaCompositionAdded, Is.True); - - var testPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + + var testPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "test") { - Alias = "test", Name = "Test", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Test", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var testAdded = seoComposition.AddPropertyType(testPropertyType, "Content"); service.Save(seoComposition); @@ -794,13 +793,13 @@ namespace Umbraco.Tests.Services service.Save(contentMetaComposition); // Act - var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content"); var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content"); @@ -840,24 +839,24 @@ namespace Umbraco.Tests.Services service.Save(advancedPage); // Act - var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content"); - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content"); - var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content"); - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content"); service.Save(basePage); @@ -913,9 +912,9 @@ namespace Umbraco.Tests.Services service.Save(contentMetaComposition); // Act - var propertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var propertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title") { - Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var addedToContentPage = contentPage.AddPropertyType(propertyType, "Content"); @@ -947,14 +946,14 @@ namespace Umbraco.Tests.Services service.Save(contentPage); // Act - var propertyTypeOne = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var propertyTypeOne = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "testTextbox") { - Alias = "testTextbox", Name = "Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var firstOneAdded = contentPage.AddPropertyType(propertyTypeOne, "Content_"); - var propertyTypeTwo = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var propertyTypeTwo = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "anotherTextbox") { - Alias = "anotherTextbox", Name = "Another Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Another Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var secondOneAdded = contentPage.AddPropertyType(propertyTypeTwo, "Content"); service.Save(contentPage); @@ -998,29 +997,29 @@ namespace Umbraco.Tests.Services service.Save(contentPage); // Act - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; - var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content_");//Will be added to the parent tab var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");//Will be added to the "Content Meta" composition service.Save(contentPage); - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; - var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "description") { - Alias = "description", Name = "Description", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Description", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; - var keywordsPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var keywordsPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "keywords") { - Alias = "keywords", Name = "Keywords", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Keywords", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content_");//Will be added to an ancestor tab var descriptionAdded = advancedPage.AddPropertyType(descriptionPropertyType, "Contentx");//Will be added to a parent tab @@ -1065,17 +1064,17 @@ namespace Umbraco.Tests.Services service.Save(contentMetaComposition); // Act - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; - var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "subtitle") { - Alias = "subtitle", Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Subtitle", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = page.AddPropertyType(bodyTextPropertyType, "Content_"); var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content"); @@ -1118,16 +1117,16 @@ namespace Umbraco.Tests.Services service.Save(contentMetaComposition); // Act - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content"); service.Save(basePage); - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content"); service.Save(contentPage); @@ -1176,16 +1175,16 @@ namespace Umbraco.Tests.Services service.Save(contentMetaComposition); // Act - var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author") { - Alias = "author", Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Author", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content"); service.Save(contentPage); - var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "bodyText") { - Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 + Name = "Body Text", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }; var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content"); service.Save(basePage); @@ -1243,7 +1242,7 @@ namespace Umbraco.Tests.Services }; var contentCollection = new PropertyTypeCollection(); - contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "componentGroup", Name = "Component Group", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "componentGroup") { Name = "Component Group", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); component.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Component", SortOrder = 1 }); return component; @@ -1264,9 +1263,8 @@ namespace Umbraco.Tests.Services Trashed = false }; - var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext) + var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext, "bannerName") { - Alias = "bannerName", Name = "Banner Name", Description = "", Mandatory = false, @@ -1292,7 +1290,7 @@ namespace Umbraco.Tests.Services }; var contentCollection = new PropertyTypeCollection(); - contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "hostname", Name = "Hostname", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "hostname") { Name = "Hostname", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); site.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Site Settings", SortOrder = 1 }); return site; @@ -1314,9 +1312,9 @@ namespace Umbraco.Tests.Services }; var contentCollection = new PropertyTypeCollection(); - contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); - contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 }); - contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "author", Name = "Author", Description = "Name of the author", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 }); + contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "title") { Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 }); + contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "bodyText") { Name = "Body Text", Description = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 }); + contentCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext, "author") { Name = "Author", Description = "Name of the author", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 }); contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 }); diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index d9cb75e587..9e2b440815 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -676,9 +676,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Int_Value_Exact() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "number") { - Alias = "number", Name = "Number", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -51 @@ -701,9 +700,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Int_Value_Greater_Than() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "number") { - Alias = "number", Name = "Number", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -51 @@ -726,9 +724,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Int_Value_Greater_Than_Equal_To() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "number") { - Alias = "number", Name = "Number", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -51 @@ -751,9 +748,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Int_Value_Less_Than() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.DateAlias, DataTypeDatabaseType.Date) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.DateAlias, DataTypeDatabaseType.Date, "number") { - Alias = "number", Name = "Number", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -51 @@ -776,9 +772,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Int_Value_Less_Than_Or_Equal() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "number") { - Alias = "number", Name = "Number", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -51 @@ -801,9 +796,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Date_Value_Exact() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "date") { - Alias = "date", Name = "Date", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -36 @@ -826,9 +820,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Date_Value_Greater_Than() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "date") { - Alias = "date", Name = "Date", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -36 @@ -851,9 +844,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Date_Value_Greater_Than_Equal_To() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "date") { - Alias = "date", Name = "Date", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -36 @@ -876,9 +868,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Date_Value_Less_Than() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "date") { - Alias = "date", Name = "Date", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -36 @@ -901,9 +892,8 @@ namespace Umbraco.Tests.Services public void Get_By_Property_Date_Value_Less_Than_Or_Equal() { IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); - memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer) + memberType.AddPropertyType(new PropertyType(Constants.PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer, "date") { - Alias = "date", Name = "Date", //NOTE: This is what really determines the db type - the above definition doesn't really do anything DataTypeDefinitionId = -36 diff --git a/src/Umbraco.Tests/Services/TagServiceTests.cs b/src/Umbraco.Tests/Services/TagServiceTests.cs index 52e02d26da..fa339729f5 100644 --- a/src/Umbraco.Tests/Services/TagServiceTests.cs +++ b/src/Umbraco.Tests/Services/TagServiceTests.cs @@ -36,9 +36,8 @@ namespace Umbraco.Tests.Services var tagService = ServiceContext.TagService; var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext) + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") { - Alias = "tags", DataTypeDefinitionId = 1041 }); contentTypeService.Save(contentType); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 0dce9281ef..3ca4d1fad4 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -58,9 +58,9 @@ ..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll - + False - ..\packages\Examine.0.1.61.2941\lib\Examine.dll + ..\packages\Examine.0.1.62.2941\lib\Examine.dll False @@ -186,6 +186,7 @@ + diff --git a/src/Umbraco.Tests/packages.config b/src/Umbraco.Tests/packages.config index 161d0065fe..28e8b6ab26 100644 --- a/src/Umbraco.Tests/packages.config +++ b/src/Umbraco.Tests/packages.config @@ -2,7 +2,7 @@ - + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index b824ccff5a..62fbc388d2 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -127,9 +127,9 @@ False ..\packages\dotless.1.4.1.0\lib\dotless.Core.dll - + False - ..\packages\Examine.0.1.61.2941\lib\Examine.dll + ..\packages\Examine.0.1.62.2941\lib\Examine.dll False diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 3de27f18a4..d9d6aa41e8 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -4,7 +4,7 @@ - + diff --git a/src/Umbraco.Web/Models/ContentExtensions.cs b/src/Umbraco.Web/Models/ContentExtensions.cs index 977f8eaf0b..53860f10eb 100644 --- a/src/Umbraco.Web/Models/ContentExtensions.cs +++ b/src/Umbraco.Web/Models/ContentExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Linq; +using umbraco.cms.businesslogic.web; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -93,5 +94,11 @@ namespace Umbraco.Web.Models var defaultLanguage = localizationService.GetAllLanguages().FirstOrDefault(); return defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode); } + + private static CultureInfo GetDefaultCulture(ILocalizationService localizationService) + { + var defaultLanguage = localizationService.GetAllLanguages().FirstOrDefault(); + return defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode); + } } } diff --git a/src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs b/src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs index e205966f78..e0b73e05f3 100644 --- a/src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs +++ b/src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs @@ -1,9 +1,10 @@ using System; +using System.Collections.Specialized; +using System.Linq; +using System.Web; using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Models; -using Umbraco.Web.PublishedCache; -using Umbraco.Web.Routing; namespace Umbraco.Web.Mvc { @@ -14,8 +15,10 @@ namespace Umbraco.Web.Mvc { private IPublishedContent _publishedContent; private readonly int _pageId; + private NameValueCollection _queryStringValues; private readonly UmbracoContext _umbracoContext; private string _url; + public string Url { get @@ -24,7 +27,7 @@ namespace Umbraco.Web.Mvc if (PublishedContent == null) { - throw new InvalidOperationException("Cannot redirect, no entity was found for id " + _pageId); + throw new InvalidOperationException(string.Format("Cannot redirect, no entity was found for id {0}", _pageId)); } var result = _umbracoContext.RoutingContext.UrlProvider.GetUrl(PublishedContent.Id); @@ -34,7 +37,7 @@ namespace Umbraco.Web.Mvc return _url; } - throw new InvalidOperationException("Could not route to entity with id " + _pageId + ", the NiceUrlProvider could not generate a URL"); + throw new InvalidOperationException(string.Format("Could not route to entity with id {0}, the NiceUrlProvider could not generate a URL", _pageId)); } } @@ -61,6 +64,26 @@ namespace Umbraco.Web.Mvc { } + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + public RedirectToUmbracoPageResult(int pageId, NameValueCollection queryStringValues) + : this(pageId, queryStringValues, UmbracoContext.Current) + { + } + + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + public RedirectToUmbracoPageResult(int pageId, string queryString) + : this(pageId, queryString, UmbracoContext.Current) + { + } + /// /// Creates a new RedirectToUmbracoResult /// @@ -70,6 +93,63 @@ namespace Umbraco.Web.Mvc { } + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + public RedirectToUmbracoPageResult(IPublishedContent publishedContent, NameValueCollection queryStringValues) + : this(publishedContent, queryStringValues, UmbracoContext.Current) + { + } + + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + public RedirectToUmbracoPageResult(IPublishedContent publishedContent, string queryString) + : this(publishedContent, queryString, UmbracoContext.Current) + { + } + + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + public RedirectToUmbracoPageResult(int pageId, UmbracoContext umbracoContext) + { + _pageId = pageId; + _umbracoContext = umbracoContext; + } + + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + /// + public RedirectToUmbracoPageResult(int pageId, NameValueCollection queryStringValues, UmbracoContext umbracoContext) + { + _pageId = pageId; + _queryStringValues = queryStringValues; + _umbracoContext = umbracoContext; + } + + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + /// + public RedirectToUmbracoPageResult(int pageId, string queryString, UmbracoContext umbracoContext) + { + _pageId = pageId; + _queryStringValues = ParseQueryString(queryString); + _umbracoContext = umbracoContext; + } + /// /// Creates a new RedirectToUmbracoResult /// @@ -82,16 +162,33 @@ namespace Umbraco.Web.Mvc _umbracoContext = umbracoContext; } - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(int pageId, UmbracoContext umbracoContext) - { - _pageId = pageId; - _umbracoContext = umbracoContext; - } + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + /// + public RedirectToUmbracoPageResult(IPublishedContent publishedContent, NameValueCollection queryStringValues, UmbracoContext umbracoContext) + { + _publishedContent = publishedContent; + _pageId = publishedContent.Id; + _queryStringValues = queryStringValues; + _umbracoContext = umbracoContext; + } + + /// + /// Creates a new RedirectToUmbracoResult + /// + /// + /// + /// + public RedirectToUmbracoPageResult(IPublishedContent publishedContent, string queryString, UmbracoContext umbracoContext) + { + _publishedContent = publishedContent; + _pageId = publishedContent.Id; + _queryStringValues = ParseQueryString(queryString); + _umbracoContext = umbracoContext; + } public override void ExecuteResult(ControllerContext context) { @@ -103,10 +200,26 @@ namespace Umbraco.Web.Mvc } var destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext); + + if (_queryStringValues != null && _queryStringValues.Count > 0) + { + destinationUrl = destinationUrl += "?" + string.Join("&", + _queryStringValues.AllKeys.Select(x => x + "=" + HttpUtility.UrlEncode(_queryStringValues[x]))); + } + context.Controller.TempData.Keep(); context.HttpContext.Response.Redirect(destinationUrl, endResponse: false); } + private NameValueCollection ParseQueryString(string queryString) + { + if (!string.IsNullOrEmpty(queryString)) + { + return HttpUtility.ParseQueryString(queryString); + } + + return null; + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index 1f2bca4144..bff312eda3 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -1,11 +1,10 @@ using System; -using System.Collections.Concurrent; using System.Web.Mvc; -using System.Web.Routing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core; using Umbraco.Web.Security; +using System.Collections.Specialized; namespace Umbraco.Web.Mvc { @@ -54,6 +53,28 @@ namespace Umbraco.Web.Mvc return new RedirectToUmbracoPageResult(pageId, UmbracoContext); } + /// + /// Redirects to the Umbraco page with the given id and passes provided querystring + /// + /// + /// + /// + protected RedirectToUmbracoPageResult RedirectToUmbracoPage(int pageId, NameValueCollection queryStringValues) + { + return new RedirectToUmbracoPageResult(pageId, queryStringValues, UmbracoContext); + } + + /// + /// Redirects to the Umbraco page with the given id and passes provided querystring + /// + /// + /// + /// + protected RedirectToUmbracoPageResult RedirectToUmbracoPage(int pageId, string queryString) + { + return new RedirectToUmbracoPageResult(pageId, queryString, UmbracoContext); + } + /// /// Redirects to the Umbraco page with the given id /// @@ -64,6 +85,28 @@ namespace Umbraco.Web.Mvc return new RedirectToUmbracoPageResult(publishedContent, UmbracoContext); } + /// + /// Redirects to the Umbraco page with the given id and passes provided querystring + /// + /// + /// + /// + protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent publishedContent, NameValueCollection queryStringValues) + { + return new RedirectToUmbracoPageResult(publishedContent, queryStringValues, UmbracoContext); + } + + /// + /// Redirects to the Umbraco page with the given id and passes provided querystring + /// + /// + /// + /// + protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent publishedContent, string queryString) + { + return new RedirectToUmbracoPageResult(publishedContent, queryString, UmbracoContext); + } + /// /// Redirects to the currently rendered Umbraco page /// @@ -73,6 +116,25 @@ namespace Umbraco.Web.Mvc return new RedirectToUmbracoPageResult(CurrentPage, UmbracoContext); } + /// + /// Redirects to the currently rendered Umbraco page and passes provided querystring + /// + /// + /// + protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage(NameValueCollection queryStringValues) + { + return new RedirectToUmbracoPageResult(CurrentPage, queryStringValues, UmbracoContext); + } + + /// + /// Redirects to the currently rendered Umbraco page and passes provided querystring + /// + /// + /// + protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage(string queryString) + { + return new RedirectToUmbracoPageResult(CurrentPage, queryString, UmbracoContext); + } /// /// Redirects to the currently rendered Umbraco URL /// diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheFilePersister.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheFilePersister.cs index 319bb874c1..8fe3b1c0ac 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheFilePersister.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheFilePersister.cs @@ -133,7 +133,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { _logger.Logger.Debug("Run now."); var doc = _content.XmlContentInternal; - await PersistXmlToFileAsync(doc); + await PersistXmlToFileAsync(doc).ConfigureAwait(false); } public bool IsAsync @@ -160,7 +160,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // create dir if it is not there, if it's there, this will proceed as normal Directory.CreateDirectory(directoryName); - await xmlDoc.SaveAsync(_xmlFileName); + await xmlDoc.SaveAsync(_xmlFileName).ConfigureAwait(false); } catch (Exception ee) { diff --git a/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs index 90da48039c..e6f4a487ec 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs @@ -3,6 +3,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Web.Routing { @@ -14,14 +15,29 @@ namespace Umbraco.Web.Routing /// public class ContentFinderByIdPath : IContentFinder { - /// + private readonly IWebRoutingSection _webRoutingSection; + + public ContentFinderByIdPath() + : this(UmbracoConfig.For.UmbracoSettings().WebRouting) + { + + } + + public ContentFinderByIdPath(IWebRoutingSection webRoutingSection) + { + _webRoutingSection = webRoutingSection; + } + + /// /// Tries to find and assign an Umbraco document to a PublishedContentRequest. /// /// The PublishedContentRequest. /// A value indicating whether an Umbraco document was found and assigned. public bool TryFindContent(PublishedContentRequest docRequest) { - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableFindContentByIdPath) + + if (docRequest.RoutingContext.UmbracoContext != null && docRequest.RoutingContext.UmbracoContext.InPreviewMode == false + && _webRoutingSection.DisableFindContentByIdPath) return false; IPublishedContent node = null; diff --git a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs index 3a5ace8af8..7f3606474a 100644 --- a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Concurrent; +using System.Globalization; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using System.Web.Hosting; using Umbraco.Core.Logging; +using Umbraco.Core.Events; namespace Umbraco.Web.Scheduling { @@ -21,6 +23,7 @@ namespace Umbraco.Web.Scheduling private readonly BlockingCollection _tasks = new BlockingCollection(); private readonly object _locker = new object(); private readonly ManualResetEventSlim _completedEvent = new ManualResetEventSlim(false); + private BackgroundTaskRunnerAwaiter _awaiter; private volatile bool _isRunning; // is running private volatile bool _isCompleted; // does not accept tasks anymore, may still be running @@ -28,10 +31,11 @@ namespace Umbraco.Web.Scheduling private CancellationTokenSource _tokenSource; - internal event EventHandler> TaskError; - internal event EventHandler> TaskStarting; - internal event EventHandler> TaskCompleted; - internal event EventHandler> TaskCancelled; + internal event TypedEventHandler, TaskEventArgs> TaskError; + internal event TypedEventHandler, TaskEventArgs> TaskStarting; + internal event TypedEventHandler, TaskEventArgs> TaskCompleted; + internal event TypedEventHandler, TaskEventArgs> TaskCancelled; + internal event TypedEventHandler, EventArgs> Completed; /// /// Initializes a new instance of the class. @@ -48,7 +52,7 @@ namespace Umbraco.Web.Scheduling { if (options == null) throw new ArgumentNullException("options"); _options = options; - + HostingEnvironment.RegisterObject(this); if (options.AutoStart) @@ -80,42 +84,40 @@ namespace Umbraco.Web.Scheduling } /// - /// Gets the status of the running task. + /// Gets an awaiter used to await the running Threading.Task. /// /// There is no running task. - /// Unless the AutoStart option is true, there will be no running task until + /// + /// Unless the AutoStart option is true, there will be no running task until /// a background task is added to the queue. Unless the KeepAlive option is true, there - /// will be no running task when the queue is empty. - public TaskStatus TaskStatus + /// will be no running task when the queue is empty. + /// + public ThreadingTaskAwaiter CurrentThreadingTask { get { if (_runningTask == null) - throw new InvalidOperationException("There is no current task."); - return _runningTask.Status; + throw new InvalidOperationException("There is no current Threading.Task."); + return new ThreadingTaskAwaiter(_runningTask); } } - + /// - /// Gets an awaiter used to await the running task. + /// Gets an awaiter used to await the BackgroundTaskRunner running operation /// - /// An awaiter for the running task. + /// An awaiter for the BackgroundTaskRunner running operation /// - /// This is just the coolest thing ever, check this article out: - /// http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115642.aspx - /// - /// So long as we have a method called GetAwaiter() that returns an instance of INotifyCompletion - /// we can await anything! :) - /// - /// There is no running task. - /// Unless the AutoStart option is true, there will be no running task until - /// a background task is added to the queue. Unless the KeepAlive option is true, there - /// will be no running task when the queue is empty. - public TaskAwaiter GetAwaiter() + /// This is used to wait until the background task runner is no longer running (IsRunning == false) + /// + /// So long as we have a method called GetAwaiter() that returns an instance of INotifyCompletion + /// we can await anything. In this case we are awaiting with a custom BackgroundTaskRunnerAwaiter + /// which waits for the Completed event to be raised. + /// ref: http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115642.aspx + /// + /// + public BackgroundTaskRunnerAwaiter GetAwaiter() { - if (_runningTask == null) - throw new InvalidOperationException("There is no current task."); - return _runningTask.GetAwaiter(); + return _awaiter ?? (_awaiter = new BackgroundTaskRunnerAwaiter(this)); } /// @@ -261,6 +263,8 @@ namespace Umbraco.Web.Scheduling _isRunning = false; // done if (_options.PreserveRunningTask == false) _runningTask = null; + //raise event + OnCompleted(); return; } } @@ -372,7 +376,8 @@ namespace Umbraco.Web.Scheduling using (bgTask) // ensure it's disposed { if (bgTask.IsAsync) - await bgTask.RunAsync(token); + //configure await = false since we don't care about the context, we're on a background thread. + await bgTask.RunAsync(token).ConfigureAwait(false); else bgTask.Run(); } @@ -388,7 +393,7 @@ namespace Umbraco.Web.Scheduling catch (Exception ex) { LogHelper.Error>("Task has failed.", ex); - } + } } #region Events @@ -402,24 +407,70 @@ namespace Umbraco.Web.Scheduling protected virtual void OnTaskStarting(TaskEventArgs e) { var handler = TaskStarting; - if (handler != null) handler(this, e); + if (handler != null) + { + try + { + handler(this, e); + } + catch (Exception ex) + { + LogHelper.Error>("TaskStarting exception occurred", ex); + } + } } protected virtual void OnTaskCompleted(TaskEventArgs e) { var handler = TaskCompleted; - if (handler != null) handler(this, e); + if (handler != null) + { + try + { + handler(this, e); + } + catch (Exception ex) + { + LogHelper.Error>("TaskCompleted exception occurred", ex); + } + } } protected virtual void OnTaskCancelled(TaskEventArgs e) { var handler = TaskCancelled; - if (handler != null) handler(this, e); + if (handler != null) + { + try + { + handler(this, e); + } + catch (Exception ex) + { + LogHelper.Error>("TaskCancelled exception occurred", ex); + } + } //dispose it e.Task.Dispose(); } + protected virtual void OnCompleted() + { + var handler = Completed; + if (handler != null) + { + try + { + handler(this, EventArgs.Empty); + } + catch (Exception ex) + { + LogHelper.Error>("OnCompleted exception occurred", ex); + } + } + } + #endregion #region IDisposable @@ -509,5 +560,7 @@ namespace Umbraco.Web.Scheduling LogHelper.Info>("Down."); } } + + } } diff --git a/src/Umbraco.Web/Scheduling/BackgroundTaskRunnerAwaiter.cs b/src/Umbraco.Web/Scheduling/BackgroundTaskRunnerAwaiter.cs new file mode 100644 index 0000000000..8332573e07 --- /dev/null +++ b/src/Umbraco.Web/Scheduling/BackgroundTaskRunnerAwaiter.cs @@ -0,0 +1,65 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Umbraco.Web.Scheduling +{ + /// + /// Custom awaiter used to await when the BackgroundTaskRunner is completed (IsRunning == false) + /// + /// + /// + /// This custom awaiter simply uses a TaskCompletionSource to set the result when the Completed event of the + /// BackgroundTaskRunner executes. + /// A custom awaiter requires implementing INotifyCompletion as well as IsCompleted, OnCompleted and GetResult + /// see: http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115642.aspx + /// + internal class BackgroundTaskRunnerAwaiter : INotifyCompletion where T : class, IBackgroundTask + { + private readonly BackgroundTaskRunner _runner; + private readonly TaskCompletionSource _tcs; + private readonly TaskAwaiter _awaiter; + + public BackgroundTaskRunnerAwaiter(BackgroundTaskRunner runner) + { + if (runner == null) throw new ArgumentNullException("runner"); + _runner = runner; + + _tcs = new TaskCompletionSource(); + + if (_runner.IsRunning) + { + _runner.Completed += (s, e) => _tcs.SetResult(0); + } + else + { + //not running, just set the result + _tcs.SetResult(0); + } + _awaiter = _tcs.Task.GetAwaiter(); + } + + public BackgroundTaskRunnerAwaiter GetAwaiter() + { + return this; + } + + /// + /// This is completed when the runner is finished running + /// + public bool IsCompleted + { + get { return _runner.IsRunning == false; } + } + + public void OnCompleted(Action continuation) + { + _awaiter.OnCompleted(continuation); + } + + public void GetResult() + { + _awaiter.GetResult(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Scheduling/ThreadingTaskAwaiter.cs b/src/Umbraco.Web/Scheduling/ThreadingTaskAwaiter.cs new file mode 100644 index 0000000000..36c00dfa9e --- /dev/null +++ b/src/Umbraco.Web/Scheduling/ThreadingTaskAwaiter.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Umbraco.Web.Scheduling +{ + /// + /// This is used to return an awaitable instance from a Task without actually returning the + /// underlying Task instance since it shouldn't be mutable. + /// + internal class ThreadingTaskAwaiter + { + private readonly Task _task; + + public ThreadingTaskAwaiter(Task task) + { + if (task == null) throw new ArgumentNullException("task"); + _task = task; + } + + /// + /// With a GetAwaiter declared it means that this instance can be awaited on with the await keyword + /// + /// + public TaskAwaiter GetAwaiter() + { + return _task.GetAwaiter(); + } + + /// + /// Gets the status of the running task. + /// + /// There is no running task. + /// Unless the AutoStart option is true, there will be no running task until + /// a background task is added to the queue. Unless the KeepAlive option is true, there + /// will be no running task when the queue is empty. + public TaskStatus Status + { + get { return _task.Status; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ffaec48edd..e8473c6ce5 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -115,9 +115,9 @@ ..\packages\dotless.1.4.1.0\lib\dotless.Core.dll - - False - ..\packages\Examine.0.1.61.2941\lib\Examine.dll + + ..\packages\Examine.0.1.62.2941\lib\Examine.dll + True False @@ -326,6 +326,7 @@ + @@ -552,6 +553,7 @@ + diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config index 0257d9b37a..9c76401b42 100644 --- a/src/Umbraco.Web/packages.config +++ b/src/Umbraco.Web/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/UmbracoExamine/UmbracoExamine.csproj b/src/UmbracoExamine/UmbracoExamine.csproj index 6e50ec5a4b..1922d86d88 100644 --- a/src/UmbracoExamine/UmbracoExamine.csproj +++ b/src/UmbracoExamine/UmbracoExamine.csproj @@ -82,9 +82,9 @@ ..\Solution Items\TheFARM-Public.snk - + False - ..\packages\Examine.0.1.61.2941\lib\Examine.dll + ..\packages\Examine.0.1.62.2941\lib\Examine.dll False diff --git a/src/UmbracoExamine/packages.config b/src/UmbracoExamine/packages.config index 47328cd5f6..caa69d63c4 100644 --- a/src/UmbracoExamine/packages.config +++ b/src/UmbracoExamine/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/umbraco.MacroEngines/packages.config b/src/umbraco.MacroEngines/packages.config index 644e7fc8dc..ef671fbcd9 100644 --- a/src/umbraco.MacroEngines/packages.config +++ b/src/umbraco.MacroEngines/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj index 58735ed15a..66fdab66c1 100644 --- a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj +++ b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj @@ -45,9 +45,9 @@ false - + False - ..\packages\Examine.0.1.61.2941\lib\Examine.dll + ..\packages\Examine.0.1.62.2941\lib\Examine.dll False