From 76bc312842a4164b7869695839cd671405b62a82 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 1 Nov 2013 18:06:58 +1100 Subject: [PATCH 1/9] Fixes an issue with empty string conversions to date time - should fail --- src/Umbraco.Core/ObjectExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/ObjectExtensions.cs b/src/Umbraco.Core/ObjectExtensions.cs index 605a6d7847..007b347aeb 100644 --- a/src/Umbraco.Core/ObjectExtensions.cs +++ b/src/Umbraco.Core/ObjectExtensions.cs @@ -198,7 +198,7 @@ namespace Umbraco.Core if (destinationType == typeof(Boolean)) return Attempt.Succeed(false); // special case for booleans, null/empty == false else if (destinationType == typeof(DateTime)) - return Attempt.Succeed(DateTime.MinValue); + return Attempt.Succeed(false); } // we have a non-empty string, look for type conversions in the expected order of frequency of use... From 267170999197beecdd7e7742acda0b1369dfbdd1 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 1 Nov 2013 09:51:54 +0100 Subject: [PATCH 2/9] U4-2518 - issue with virtual dir named Umbraco --- src/Umbraco.Core/Configuration/GlobalSettings.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 8b8a936281..4526ece5f3 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -175,7 +175,10 @@ namespace Umbraco.Core.Configuration { throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified"); } - return Path.TrimStart(SystemDirectories.Root).TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower(); + var path = Path; + if (path.StartsWith(SystemDirectories.Root)) // beware of TrimStart, see U4-2518 + path = path.Substring(SystemDirectories.Root.Length); + return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower(); } } From b75a9cc34bdef15eddef21277d6148a527efd26e Mon Sep 17 00:00:00 2001 From: Shannon Date: Sat, 2 Nov 2013 13:22:48 +1100 Subject: [PATCH 3/9] Changed the naming to PublishedContentQuery and TagQuery --- ...eryContext.cs => PublishedContentQuery.cs} | 4 +- .../{TagQueryContext.cs => TagQuery.cs} | 4 +- src/Umbraco.Web/Umbraco.Web.csproj | 4 +- src/Umbraco.Web/UmbracoHelper.cs | 126 +++++++++--------- src/Umbraco.Web/WebServices/TagsController.cs | 12 +- 5 files changed, 75 insertions(+), 75 deletions(-) rename src/Umbraco.Web/{PublishedQueryContext.cs => PublishedContentQuery.cs} (99%) rename src/Umbraco.Web/{TagQueryContext.cs => TagQuery.cs} (97%) diff --git a/src/Umbraco.Web/PublishedQueryContext.cs b/src/Umbraco.Web/PublishedContentQuery.cs similarity index 99% rename from src/Umbraco.Web/PublishedQueryContext.cs rename to src/Umbraco.Web/PublishedContentQuery.cs index 6b69faad6b..f759d42e16 100644 --- a/src/Umbraco.Web/PublishedQueryContext.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -13,12 +13,12 @@ namespace Umbraco.Web /// /// A class used to query for published content, media items /// - public class PublishedQueryContext + public class PublishedContentQuery { private readonly ContextualPublishedContentCache _contentCache; private readonly ContextualPublishedMediaCache _mediaCache; - public PublishedQueryContext(ContextualPublishedContentCache contentCache, ContextualPublishedMediaCache mediaCache) + public PublishedContentQuery(ContextualPublishedContentCache contentCache, ContextualPublishedMediaCache mediaCache) { _contentCache = contentCache; _mediaCache = mediaCache; diff --git a/src/Umbraco.Web/TagQueryContext.cs b/src/Umbraco.Web/TagQuery.cs similarity index 97% rename from src/Umbraco.Web/TagQueryContext.cs rename to src/Umbraco.Web/TagQuery.cs index fac291a77b..8d4a857464 100644 --- a/src/Umbraco.Web/TagQueryContext.cs +++ b/src/Umbraco.Web/TagQuery.cs @@ -9,11 +9,11 @@ namespace Umbraco.Web /// /// A class that exposes methods used to query tag data in views /// - public class TagQueryContext + public class TagQuery { private readonly ITagService _tagService; - public TagQueryContext(ITagService tagService) + public TagQuery(ITagService tagService) { if (tagService == null) throw new ArgumentNullException("tagService"); _tagService = tagService; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 0539fc5f61..f9d62c1aa7 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -401,9 +401,9 @@ - + - + diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index a9ccba55f4..0275ba2ce5 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -32,23 +32,23 @@ namespace Umbraco.Web { private readonly UmbracoContext _umbracoContext; private readonly IPublishedContent _currentPage; - private PublishedQueryContext _queryContext; - private TagQueryContext _tagContext; + private PublishedContentQuery _query; + private TagQuery _tag; /// /// Lazy instantiates the tag context /// - public TagQueryContext Tags + public TagQuery TagQuery { - get { return _tagContext ?? (_tagContext = new TagQueryContext(UmbracoContext.Application.Services.TagService)); } + get { return _tag ?? (_tag = new TagQuery(UmbracoContext.Application.Services.TagService)); } } /// /// Lazy instantiates the query context /// - public PublishedQueryContext QueryContext + public PublishedContentQuery ContentQuery { - get { return _queryContext ?? (_queryContext = new PublishedQueryContext(UmbracoContext.ContentCache, UmbracoContext.MediaCache)); } + get { return _query ?? (_query = new PublishedContentQuery(UmbracoContext.ContentCache, UmbracoContext.MediaCache)); } } /// @@ -73,13 +73,13 @@ namespace Umbraco.Web { } - public UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content, PublishedQueryContext queryContext) + public UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content, PublishedContentQuery query) : this(umbracoContext) { if (content == null) throw new ArgumentNullException("content"); - if (queryContext == null) throw new ArgumentNullException("queryContext"); + if (query == null) throw new ArgumentNullException("query"); _currentPage = content; - _queryContext = queryContext; + _query = query; } /// @@ -109,11 +109,11 @@ namespace Umbraco.Web } } - public UmbracoHelper(UmbracoContext umbracoContext, PublishedQueryContext queryContext) + public UmbracoHelper(UmbracoContext umbracoContext, PublishedContentQuery query) : this(umbracoContext) { - if (queryContext == null) throw new ArgumentNullException("queryContext"); - _queryContext = queryContext; + if (query == null) throw new ArgumentNullException("query"); + _query = query; } /// @@ -576,140 +576,140 @@ namespace Umbraco.Web public IPublishedContent TypedContent(object id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.TypedContent(intId) : null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.TypedContent(intId) : null; } public IPublishedContent TypedContent(int id) { - return QueryContext.TypedContent(id); + return ContentQuery.TypedContent(id); } public IPublishedContent TypedContent(string id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.TypedContent(intId) : null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.TypedContent(intId) : null; } public IPublishedContent TypedContentSingleAtXPath(string xpath, params XPathVariable[] vars) { - return QueryContext.TypedContentSingleAtXPath(xpath, vars); + return ContentQuery.TypedContentSingleAtXPath(xpath, vars); } public IEnumerable TypedContent(params object[] ids) { - return QueryContext.TypedContent(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedContent(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedContent(params int[] ids) { - return QueryContext.TypedContent(ids); + return ContentQuery.TypedContent(ids); } public IEnumerable TypedContent(params string[] ids) { - return QueryContext.TypedContent(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedContent(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedContent(IEnumerable ids) { - return QueryContext.TypedContent(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedContent(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedContent(IEnumerable ids) { - return QueryContext.TypedContent(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedContent(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedContent(IEnumerable ids) { - return QueryContext.TypedContent(ids); + return ContentQuery.TypedContent(ids); } public IEnumerable TypedContentAtXPath(string xpath, params XPathVariable[] vars) { - return QueryContext.TypedContentAtXPath(xpath, vars); + return ContentQuery.TypedContentAtXPath(xpath, vars); } public IEnumerable TypedContentAtXPath(XPathExpression xpath, params XPathVariable[] vars) { - return QueryContext.TypedContentAtXPath(xpath, vars); + return ContentQuery.TypedContentAtXPath(xpath, vars); } public IEnumerable TypedContentAtRoot() { - return QueryContext.TypedContentAtRoot(); + return ContentQuery.TypedContentAtRoot(); } public dynamic Content(object id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.Content(intId) : DynamicNull.Null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.Content(intId) : DynamicNull.Null; } public dynamic Content(int id) { - return QueryContext.Content(id); + return ContentQuery.Content(id); } public dynamic Content(string id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.Content(intId) : DynamicNull.Null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.Content(intId) : DynamicNull.Null; } public dynamic ContentSingleAtXPath(string xpath, params XPathVariable[] vars) { - return QueryContext.ContentSingleAtXPath(xpath, vars); + return ContentQuery.ContentSingleAtXPath(xpath, vars); } public dynamic ContentSingleAtXPath(XPathExpression xpath, params XPathVariable[] vars) { - return QueryContext.ContentSingleAtXPath(xpath, vars); + return ContentQuery.ContentSingleAtXPath(xpath, vars); } public dynamic Content(params object[] ids) { - return QueryContext.Content(ConvertIdsObjectToInts(ids)); + return ContentQuery.Content(ConvertIdsObjectToInts(ids)); } public dynamic Content(params int[] ids) { - return QueryContext.Content(ids); + return ContentQuery.Content(ids); } public dynamic Content(params string[] ids) { - return QueryContext.Content(ConvertIdsObjectToInts(ids)); + return ContentQuery.Content(ConvertIdsObjectToInts(ids)); } public dynamic Content(IEnumerable ids) { - return QueryContext.Content(ConvertIdsObjectToInts(ids)); + return ContentQuery.Content(ConvertIdsObjectToInts(ids)); } public dynamic Content(IEnumerable ids) { - return QueryContext.Content(ids); + return ContentQuery.Content(ids); } public dynamic Content(IEnumerable ids) { - return QueryContext.Content(ConvertIdsObjectToInts(ids)); + return ContentQuery.Content(ConvertIdsObjectToInts(ids)); } public dynamic ContentAtXPath(string xpath, params XPathVariable[] vars) { - return QueryContext.ContentAtXPath(xpath, vars); + return ContentQuery.ContentAtXPath(xpath, vars); } public dynamic ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars) { - return QueryContext.ContentAtXPath(xpath, vars); + return ContentQuery.ContentAtXPath(xpath, vars); } public dynamic ContentAtRoot() { - return QueryContext.ContentAtRoot(); + return ContentQuery.ContentAtRoot(); } private bool ConvertIdObjectToInt(object id, out int intId) @@ -760,105 +760,105 @@ namespace Umbraco.Web public IPublishedContent TypedMedia(object id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.TypedMedia(intId) : null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.TypedMedia(intId) : null; } public IPublishedContent TypedMedia(int id) { - return QueryContext.TypedMedia(id); + return ContentQuery.TypedMedia(id); } public IPublishedContent TypedMedia(string id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.TypedMedia(intId) : null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.TypedMedia(intId) : null; } public IEnumerable TypedMedia(params object[] ids) { - return QueryContext.TypedMedia(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedMedia(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedMedia(params int[] ids) { - return QueryContext.TypedMedia(ids); + return ContentQuery.TypedMedia(ids); } public IEnumerable TypedMedia(params string[] ids) { - return QueryContext.TypedMedia(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedMedia(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedMedia(IEnumerable ids) { - return QueryContext.TypedMedia(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedMedia(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedMedia(IEnumerable ids) { - return QueryContext.TypedMedia(ids); + return ContentQuery.TypedMedia(ids); } public IEnumerable TypedMedia(IEnumerable ids) { - return QueryContext.TypedMedia(ConvertIdsObjectToInts(ids)); + return ContentQuery.TypedMedia(ConvertIdsObjectToInts(ids)); } public IEnumerable TypedMediaAtRoot() { - return QueryContext.TypedMediaAtRoot(); + return ContentQuery.TypedMediaAtRoot(); } public dynamic Media(object id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.Media(intId) : DynamicNull.Null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.Media(intId) : DynamicNull.Null; } public dynamic Media(int id) { - return QueryContext.Media(id); + return ContentQuery.Media(id); } public dynamic Media(string id) { int intId; - return ConvertIdObjectToInt(id, out intId) ? QueryContext.Media(intId) : DynamicNull.Null; + return ConvertIdObjectToInt(id, out intId) ? ContentQuery.Media(intId) : DynamicNull.Null; } public dynamic Media(params object[] ids) { - return QueryContext.Media(ConvertIdsObjectToInts(ids)); + return ContentQuery.Media(ConvertIdsObjectToInts(ids)); } public dynamic Media(params int[] ids) { - return QueryContext.Media(ids); + return ContentQuery.Media(ids); } public dynamic Media(params string[] ids) { - return QueryContext.Media(ConvertIdsObjectToInts(ids)); + return ContentQuery.Media(ConvertIdsObjectToInts(ids)); } public dynamic Media(IEnumerable ids) { - return QueryContext.Media(ConvertIdsObjectToInts(ids)); + return ContentQuery.Media(ConvertIdsObjectToInts(ids)); } public dynamic Media(IEnumerable ids) { - return QueryContext.Media(ids); + return ContentQuery.Media(ids); } public dynamic Media(IEnumerable ids) { - return QueryContext.Media(ConvertIdsObjectToInts(ids)); + return ContentQuery.Media(ConvertIdsObjectToInts(ids)); } public dynamic MediaAtRoot() { - return QueryContext.MediaAtRoot(); + return ContentQuery.MediaAtRoot(); } #endregion @@ -874,7 +874,7 @@ namespace Umbraco.Web /// public dynamic Search(string term, bool useWildCards = true, string searchProvider = null) { - return QueryContext.Search(term, useWildCards, searchProvider); + return ContentQuery.Search(term, useWildCards, searchProvider); } /// @@ -885,7 +885,7 @@ namespace Umbraco.Web /// public dynamic Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) { - return QueryContext.Search(criteria, searchProvider); + return ContentQuery.Search(criteria, searchProvider); } /// @@ -897,7 +897,7 @@ namespace Umbraco.Web /// public IEnumerable TypedSearch(string term, bool useWildCards = true, string searchProvider = null) { - return QueryContext.Search(term, useWildCards, searchProvider); + return ContentQuery.Search(term, useWildCards, searchProvider); } /// @@ -908,7 +908,7 @@ namespace Umbraco.Web /// public IEnumerable TypedSearch(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) { - return QueryContext.Search(criteria, searchProvider); + return ContentQuery.Search(criteria, searchProvider); } #endregion diff --git a/src/Umbraco.Web/WebServices/TagsController.cs b/src/Umbraco.Web/WebServices/TagsController.cs index b9a4cca105..6d22a54f17 100644 --- a/src/Umbraco.Web/WebServices/TagsController.cs +++ b/src/Umbraco.Web/WebServices/TagsController.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.WebServices /// public IEnumerable GetAllTags(string group = null) { - return Umbraco.Tags.GetAllTags(group); + return Umbraco.TagQuery.GetAllTags(group); } /// @@ -33,7 +33,7 @@ namespace Umbraco.Web.WebServices /// public IEnumerable GetAllContentTags(string group = null) { - return Umbraco.Tags.GetAllContentTags(group); + return Umbraco.TagQuery.GetAllContentTags(group); } /// @@ -43,7 +43,7 @@ namespace Umbraco.Web.WebServices /// public IEnumerable GetAllMediaTags(string group = null) { - return Umbraco.Tags.GetAllMediaTags(group); + return Umbraco.TagQuery.GetAllMediaTags(group); } /// @@ -53,7 +53,7 @@ namespace Umbraco.Web.WebServices /// public IEnumerable GetAllMemberTags(string group = null) { - return Umbraco.Tags.GetAllMemberTags(group); + return Umbraco.TagQuery.GetAllMemberTags(group); } /// @@ -65,7 +65,7 @@ namespace Umbraco.Web.WebServices /// public IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string tagGroup = null) { - return Umbraco.Tags.GetTagsForProperty(contentId, propertyTypeAlias, tagGroup); + return Umbraco.TagQuery.GetTagsForProperty(contentId, propertyTypeAlias, tagGroup); } /// @@ -76,7 +76,7 @@ namespace Umbraco.Web.WebServices /// public IEnumerable GetTagsForEntity(int contentId, string tagGroup = null) { - return Umbraco.Tags.GetTagsForEntity(contentId, tagGroup); + return Umbraco.TagQuery.GetTagsForEntity(contentId, tagGroup); } } From a348177126afd1a557f2758cfa9eec9e74e63429 Mon Sep 17 00:00:00 2001 From: Shannon Date: Sat, 2 Nov 2013 15:18:08 +1100 Subject: [PATCH 4/9] Fixes object extensions and tests --- src/Umbraco.Core/ObjectExtensions.cs | 131 +++++++++++---------- src/Umbraco.Tests/ObjectExtensionsTests.cs | 17 +++ 2 files changed, 87 insertions(+), 61 deletions(-) diff --git a/src/Umbraco.Core/ObjectExtensions.cs b/src/Umbraco.Core/ObjectExtensions.cs index 2b55a2276d..603c508e0f 100644 --- a/src/Umbraco.Core/ObjectExtensions.cs +++ b/src/Umbraco.Core/ObjectExtensions.cs @@ -97,8 +97,17 @@ namespace Umbraco.Core // if we've got a nullable of something, we try to convert directly to that thing. if (destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof(Nullable<>)) { + var underlyingType = Nullable.GetUnderlyingType(destinationType); + + //special case for empty strings for bools/dates which should return null if an empty string + var asString = input as string; + if (asString != null && string.IsNullOrEmpty(asString) && (underlyingType == typeof(DateTime) || underlyingType == typeof(bool))) + { + return Attempt.Succeed(null); + } + // recursively call into myself with the inner (not-nullable) type and handle the outcome - var nonNullable = input.TryConvertTo(Nullable.GetUnderlyingType(destinationType)); + var nonNullable = input.TryConvertTo(underlyingType); // and if sucessful, fall on through to rewrap in a nullable; if failed, pass on the exception if (nonNullable.Success) @@ -202,78 +211,78 @@ namespace Umbraco.Core if (destinationType == typeof(string)) return Attempt.Succeed(input); - if (input == null || input.Length == 0) + if (string.IsNullOrEmpty(input)) { if (destinationType == typeof(Boolean)) return Attempt.Succeed(false); // special case for booleans, null/empty == false - else if (destinationType == typeof(DateTime)) - return Attempt.Succeed(false); + if (destinationType == typeof(DateTime)) + return Attempt.Succeed(DateTime.MinValue); } // we have a non-empty string, look for type conversions in the expected order of frequency of use... if (destinationType.IsPrimitive) { - if (destinationType == typeof(Int32)) + if (destinationType == typeof(Int32)) { Int32 value; return Int32.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); } - else if (destinationType == typeof(Int64)) - { - Int64 value; - return Int64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Boolean)) - { - Boolean value; - if (Boolean.TryParse(input, out value)) - return Attempt.Succeed(value); // don't declare failure so the CustomBooleanTypeConverter can try - } - else if (destinationType == typeof(Int16)) - { - Int16 value; - return Int16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Double)) - { - Double value; - return Double.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Single)) - { - Single value; - return Single.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Char)) - { - Char value; - return Char.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Byte)) - { - Byte value; - return Byte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(SByte)) - { - SByte value; - return SByte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(UInt32)) - { - UInt32 value; - return UInt32.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(UInt16)) - { - UInt16 value; - return UInt16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(UInt64)) - { - UInt64 value; - return UInt64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } + if (destinationType == typeof(Int64)) + { + Int64 value; + return Int64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + if (destinationType == typeof(Boolean)) + { + Boolean value; + if (Boolean.TryParse(input, out value)) + return Attempt.Succeed(value); // don't declare failure so the CustomBooleanTypeConverter can try + } + else if (destinationType == typeof(Int16)) + { + Int16 value; + return Int16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Double)) + { + Double value; + return Double.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Single)) + { + Single value; + return Single.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Char)) + { + Char value; + return Char.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Byte)) + { + Byte value; + return Byte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(SByte)) + { + SByte value; + return SByte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(UInt32)) + { + UInt32 value; + return UInt32.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(UInt16)) + { + UInt16 value; + return UInt16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(UInt64)) + { + UInt64 value; + return UInt64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } } else if (destinationType == typeof(Guid)) { diff --git a/src/Umbraco.Tests/ObjectExtensionsTests.cs b/src/Umbraco.Tests/ObjectExtensionsTests.cs index f42f2445c2..b98e7607bb 100644 --- a/src/Umbraco.Tests/ObjectExtensionsTests.cs +++ b/src/Umbraco.Tests/ObjectExtensionsTests.cs @@ -114,6 +114,23 @@ namespace Umbraco.Tests Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value, testCase.Key); } } + + [Test] + public virtual void CanConvertBlankStringToNullDateTime() + { + var result = "".TryConvertTo(); + Assert.IsTrue(result.Success); + Assert.IsNull(result.Result); + } + + [Test] + public virtual void CanConvertBlankStringToNullBool() + { + var result = "".TryConvertTo(); + Assert.IsTrue(result.Success); + Assert.IsNull(result.Result); + } + [Test] public virtual void CanConvertBlankStringToDateTime() { From 37967973a0a0043db6beb7b3d9e387cf9fdf323a Mon Sep 17 00:00:00 2001 From: Shannon Date: Sat, 2 Nov 2013 15:18:29 +1100 Subject: [PATCH 5/9] Fixes config tests since we've removed this section --- .../UmbracoSettings/umbracoSettings.config | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config index c245b29154..363d0dd50a 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config @@ -96,20 +96,6 @@ error handler is defined then you'll see the Yellow Screen Of Death (YSOD) error page. Note the error can also be handled by the umbraco.macro.Error event, where you can log/alarm with your own code and change the behaviour per event. --> inline - - - HideFileDuplicates ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd From 45d339928ab5979b91e23785cc8161b2ab1dd8cc Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Sun, 3 Nov 2013 10:57:42 +0100 Subject: [PATCH 6/9] Include missing System.Net.Http/System.Net.Http.WebRequest --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 5291f937a8..09ba05f489 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -183,7 +183,9 @@ - + + True + ..\packages\Microsoft.Net.Http.2.2.15\lib\net45\System.Net.Http.Extensions.dll @@ -193,7 +195,9 @@ ..\packages\Microsoft.Net.Http.2.2.15\lib\net45\System.Net.Http.Primitives.dll - + + True + From 94de454264dda5ad3b16012fe2e3c82059e0cd3c Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Nov 2013 17:24:25 +1100 Subject: [PATCH 7/9] Fixing unit tests --- src/Umbraco.Web/UI/LegacyDialogTask.cs | 1 + .../umbraco/create/PartialViewMacrosTasks.cs | 66 +++++++------------ .../umbraco/create/PartialViewTasks.cs | 2 +- src/umbraco.interfaces/ITask.cs | 1 + src/umbraco.interfaces/ITaskReturnUrl.cs | 3 + 5 files changed, 28 insertions(+), 45 deletions(-) diff --git a/src/Umbraco.Web/UI/LegacyDialogTask.cs b/src/Umbraco.Web/UI/LegacyDialogTask.cs index 824d753ebe..537141e30a 100644 --- a/src/Umbraco.Web/UI/LegacyDialogTask.cs +++ b/src/Umbraco.Web/UI/LegacyDialogTask.cs @@ -22,6 +22,7 @@ namespace Umbraco.Web.UI /// specific app, they'd still be able to execute code to create/delete for any ITask regardless of what app /// they have access to. /// + [Obsolete("ITask is used for legacy webforms back office editors, change to using the v7 angular approach")] public abstract class LegacyDialogTask : ITaskReturnUrl, IAssignedApp { public virtual int ParentID { get; set; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs index f939ba51a9..216bcd15e9 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs @@ -4,8 +4,10 @@ using Umbraco.Core.CodeAnnotations; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Web.Mvc; +using Umbraco.Web.UI; using umbraco.BasePages; using Umbraco.Core; +using umbraco.BusinessLogic; namespace umbraco { @@ -13,13 +15,10 @@ namespace umbraco /// The UI 'tasks' for the create dialog and delete processes /// [UmbracoWillObsolete("http://issues.umbraco.org/issue/U4-1373", "This will one day be removed when we overhaul the create process")] - public class PartialViewMacroTasks : interfaces.ITaskReturnUrl + public class PartialViewMacroTasks : LegacyDialogTask { - private string _alias; - private int _parentId; - private int _typeId; - private int _userId; - + private string _returnUrl = ""; + protected virtual string EditViewFile { get { return "Settings/Views/EditView.aspx"; } @@ -35,34 +34,11 @@ namespace umbraco get { return "MacroPartials"; } } - public int UserId + public override bool PerformSave() { - set { _userId = value; } - } - public int TypeID - { - set { _typeId = value; } - get { return _typeId; } - } - - - public string Alias - { - set { _alias = value; } - get { return _alias; } - } - - public int ParentID - { - set { _parentId = value; } - get { return _parentId; } - } - - public bool Save() - { - var pipesIndex = _alias.IndexOf("|||", System.StringComparison.Ordinal); - var template = _alias.Substring(0, pipesIndex).Trim(); - var fileName = _alias.Substring(pipesIndex + 3, _alias.Length - pipesIndex - 3) + ".cshtml"; + var pipesIndex = Alias.IndexOf("|||", System.StringComparison.Ordinal); + var template = Alias.Substring(0, pipesIndex).Trim(); + var fileName = Alias.Substring(pipesIndex + 3, Alias.Length - pipesIndex - 3) + ".cshtml"; var fullFilePath = IOHelper.MapPath(BasePath + fileName); @@ -97,27 +73,29 @@ namespace umbraco return true; } - public bool Delete() + public override string ReturnUrl { - var path = IOHelper.MapPath(BasePath + _alias.TrimStart('/')); + get { return _returnUrl; } + } + + public override string AssignedApp + { + get { return DefaultApps.developer.ToString(); } + } + + public override bool PerformDelete() + { + var path = IOHelper.MapPath(BasePath + Alias.TrimStart('/')); if (File.Exists(path)) File.Delete(path); else if (Directory.Exists(path)) Directory.Delete(path, true); - LogHelper.Info(string.Format("{0} Deleted by user {1}", _alias, UmbracoEnsuredPage.CurrentUser.Id)); + LogHelper.Info(string.Format("{0} Deleted by user {1}", Alias, User.Id)); return true; } - #region ITaskReturnUrl Members - private string _returnUrl = ""; - public string ReturnUrl - { - get { return _returnUrl; } - } - - #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs index 37983a5343..87e5abd1e8 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs @@ -107,4 +107,4 @@ namespace umbraco } } -} +} diff --git a/src/umbraco.interfaces/ITask.cs b/src/umbraco.interfaces/ITask.cs index 0b50fcc541..8ea902cc39 100644 --- a/src/umbraco.interfaces/ITask.cs +++ b/src/umbraco.interfaces/ITask.cs @@ -5,6 +5,7 @@ namespace umbraco.interfaces /// /// Summary description for ITask. /// + [Obsolete("ITask is used for legacy webforms back office editors, change to using the v7 angular approach")] public interface ITask { int ParentID {set; get;} diff --git a/src/umbraco.interfaces/ITaskReturnUrl.cs b/src/umbraco.interfaces/ITaskReturnUrl.cs index 687ddd8a14..98b132689c 100644 --- a/src/umbraco.interfaces/ITaskReturnUrl.cs +++ b/src/umbraco.interfaces/ITaskReturnUrl.cs @@ -1,5 +1,8 @@ +using System; + namespace umbraco.interfaces { + [Obsolete("ITask is used for legacy webforms back office editors, change to using the v7 angular approach")] public interface ITaskReturnUrl : ITask { string ReturnUrl {get;} From 365eb6497fef62b9af30611fa6f43bdbe290e5bd Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Nov 2013 18:12:37 +1100 Subject: [PATCH 8/9] Fixes an issue with packaging service with property alias changes which fixes part of another test and I think the issue per was having with package installs --- src/Umbraco.Core/Services/PackagingService.cs | 91 ++++++++++--------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index 873145166b..1671d3ae89 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -32,15 +33,15 @@ namespace Umbraco.Core.Services private readonly RepositoryFactory _repositoryFactory; private readonly IDatabaseUnitOfWorkProvider _uowProvider; private Dictionary _importedContentTypes; - - - public PackagingService(IContentService contentService, - IContentTypeService contentTypeService, - IMediaService mediaService, - IDataTypeService dataTypeService, - IFileService fileService, + + + public PackagingService(IContentService contentService, + IContentTypeService contentTypeService, + IMediaService mediaService, + IDataTypeService dataTypeService, + IFileService fileService, ILocalizationService localizationService, - RepositoryFactory repositoryFactory, + RepositoryFactory repositoryFactory, IDatabaseUnitOfWorkProvider uowProvider) { _contentService = contentService; @@ -56,7 +57,7 @@ namespace Umbraco.Core.Services } #region Generic export methods - + internal void ExportToFile(string absoluteFilePath, string nodeType, int id) { XElement xml = null; @@ -91,7 +92,7 @@ namespace Umbraco.Core.Services xml = Export(dataType); } - if(xml != null) + if (xml != null) xml.Save(absoluteFilePath); } @@ -293,7 +294,7 @@ namespace Umbraco.Core.Services var properties = from property in element.Elements() where property.Attribute("isDoc") == null select property; - + IContent content = parent == null ? new Content(nodeName, parentId, contentType) { @@ -324,7 +325,7 @@ namespace Umbraco.Core.Services { propertyValueList.Add(dtos.Single(x => x.Value == preValue).Id.ToString(CultureInfo.InvariantCulture)); } - + propertyValue = string.Join(",", propertyValueList.ToArray()); } @@ -355,7 +356,7 @@ namespace Umbraco.Core.Services new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString())); var masterContentType = contentType.CompositionAliases().FirstOrDefault(); - if(masterContentType != null) + if (masterContentType != null) info.Add(new XElement("Master", masterContentType)); var allowedTemplates = new XElement("AllowedTemplates"); @@ -364,7 +365,7 @@ namespace Umbraco.Core.Services allowedTemplates.Add(new XElement("Template", template.Alias)); } info.Add(allowedTemplates); - if(contentType.DefaultTemplate != null && contentType.DefaultTemplate.Id != 0) + if (contentType.DefaultTemplate != null && contentType.DefaultTemplate.Id != 0) info.Add(new XElement("DefaultTemplate", contentType.DefaultTemplate.Alias)); else info.Add(new XElement("DefaultTemplate", "")); @@ -391,7 +392,7 @@ namespace Umbraco.Core.Services new XElement("Description", new XCData(propertyType.Description))); genericProperties.Add(genericProperty); } - + var tabs = new XElement("Tabs"); foreach (var propertyGroup in contentType.PropertyGroups) { @@ -541,7 +542,7 @@ namespace Umbraco.Core.Services var template = _fileService.GetTemplate(alias.ToSafeAlias()); if (template != null) { - if(allowedTemplates.Any(x => x.Id == template.Id)) continue; + if (allowedTemplates.Any(x => x.Id == template.Id)) continue; allowedTemplates.Add(template); } else @@ -598,40 +599,46 @@ namespace Umbraco.Core.Services var dataTypeDefinitionId = new Guid(property.Element("Definition").Value);//Unique Id for a DataTypeDefinition var dataTypeDefinition = _dataTypeService.GetDataTypeDefinitionById(dataTypeDefinitionId); - + //If no DataTypeDefinition with the guid from the xml wasn't found OR the ControlId on the DataTypeDefinition didn't match the DataType Id //We look up a DataTypeDefinition that matches + + //we'll check if it is a GUID (legacy id for a property editor) + var legacyPropertyEditorId = Guid.Empty; + Guid.TryParse(property.Element("Type").Value, out legacyPropertyEditorId); + //get the alias as a string for use below + var propertyEditorAlias = property.Element("Type").Value.Trim(); + + //If no DataTypeDefinition with the guid from the xml wasn't found OR the ControlId on the DataTypeDefinition didn't match the DataType Id + //We look up a DataTypeDefinition that matches + if (dataTypeDefinition == null) { - //we'll check if it is a GUID (legacy id for a property editor) - Guid legacyPropertyEditorId; - if (Guid.TryParse(property.Element("Type").Value, out legacyPropertyEditorId)) + var dataTypeDefinitions = legacyPropertyEditorId != Guid.Empty + ? _dataTypeService.GetDataTypeDefinitionByControlId(legacyPropertyEditorId) + : _dataTypeService.GetDataTypeDefinitionByPropertyEditorAlias(propertyEditorAlias); + if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) { - if (dataTypeDefinition.ControlId != legacyPropertyEditorId) - { - var dataTypeDefinitions = _dataTypeService.GetDataTypeDefinitionByControlId(legacyPropertyEditorId); - if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) - { - dataTypeDefinition = dataTypeDefinitions.First(); - } - } + dataTypeDefinition = dataTypeDefinitions.First(); } - else + } + else if (legacyPropertyEditorId != Guid.Empty && dataTypeDefinition.ControlId != legacyPropertyEditorId) + { + var dataTypeDefinitions = _dataTypeService.GetDataTypeDefinitionByControlId(legacyPropertyEditorId); + if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) { - //check against the property editor string alias - var propertyEditorAlias = property.Element("Type").Value.Trim(); - if (dataTypeDefinition.PropertyEditorAlias != propertyEditorAlias) - { - var dataTypeDefinitions = _dataTypeService.GetDataTypeDefinitionByPropertyEditorAlias(propertyEditorAlias); - if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) - { - dataTypeDefinition = dataTypeDefinitions.First(); - } - } + dataTypeDefinition = dataTypeDefinitions.First(); + } + } + else if (dataTypeDefinition.PropertyEditorAlias != propertyEditorAlias) + { + var dataTypeDefinitions = _dataTypeService.GetDataTypeDefinitionByPropertyEditorAlias(propertyEditorAlias); + if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) + { + dataTypeDefinition = dataTypeDefinitions.First(); } } - // For backwards compatibility, if no datatype with that ID can be found, we're letting this fail silently. // This means that the property will not be created. if (dataTypeDefinition == null) @@ -790,7 +797,7 @@ namespace Umbraco.Core.Services var databaseType = databaseTypeAttribute != null ? databaseTypeAttribute.Value.EnumParse(true) : DataTypeDatabaseType.Ntext; - + //check if the Id was a GUID, that means it is referenced using the legacy property editor GUID id if (legacyPropertyEditorId != Guid.Empty) { @@ -813,7 +820,7 @@ namespace Umbraco.Core.Services }; dataTypes.Add(dataTypeDefinitionName, dataTypeDefinition); } - + } } From bc0da04470a76a6a6dacad311de98fb63d0f0af1 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Nov 2013 18:27:08 +1100 Subject: [PATCH 9/9] Fixes another issue with the installer and detecting macros --- src/umbraco.cms/businesslogic/Packager/Installer.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/umbraco.cms/businesslogic/Packager/Installer.cs b/src/umbraco.cms/businesslogic/Packager/Installer.cs index 01dc2522bf..fd121025b9 100644 --- a/src/umbraco.cms/businesslogic/Packager/Installer.cs +++ b/src/umbraco.cms/businesslogic/Packager/Installer.cs @@ -622,13 +622,12 @@ namespace umbraco.cms.businesslogic.packager var alias = n.SelectSingleNode("alias").InnerText; if (!string.IsNullOrEmpty(alias)) { - try + var m = ApplicationContext.Current.Services.MacroService.GetByAlias(alias); + if (m != null) { - var m = new Macro(alias); - this.ContainsMacroConflict = true; - this._conflictingMacroAliases.Add(m.Name, alias); - } - catch (IndexOutOfRangeException) { } //thrown when the alias doesn't exist in the DB, ie - macro not there + ContainsMacroConflict = true; + _conflictingMacroAliases.Add(m.Name, alias); + } } }