diff --git a/.gitignore b/.gitignore index ebee9f6ae9..04e39e37c9 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.* src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js +src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index 0c7d51334e..cba4de7cbe 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -33,8 +33,8 @@ - - + + diff --git a/src/NuGet.Config b/src/NuGet.Config new file mode 100644 index 0000000000..f8a7d20499 --- /dev/null +++ b/src/NuGet.Config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs index 55c1fe505f..dc3b2f3e8b 100644 --- a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs +++ b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs @@ -80,9 +80,6 @@ namespace Umbraco.Core.Persistence var creation = new DatabaseSchemaCreation(_db, _logger, _syntaxProvider); creation.InitializeDatabaseSchema(); - //Now ensure to cretae the tag in the db for the current migration version - migrationEntryService.CreateEntry(GlobalSettings.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion()); - _logger.Info("Finalized database schema creation"); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index c36e0850c1..fbe7675836 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -86,11 +87,17 @@ namespace Umbraco.Core.Persistence.Migrations.Initial { CreateUmbracoRelationTypeData(); } + if (tableName.Equals("cmsTaskType")) { CreateCmsTaskTypeData(); } + if (tableName.Equals("umbracoMigration")) + { + CreateUmbracoMigrationData(); + } + _logger.Info(string.Format("Done creating data in table {0}", tableName)); } @@ -274,5 +281,18 @@ namespace Umbraco.Core.Persistence.Migrations.Initial { _database.Insert("cmsTaskType", "id", false, new TaskTypeDto { Id = 1, Alias = "toTranslate" }); } + + private void CreateUmbracoMigrationData() + { + var dto = new MigrationDto + { + Id = 1, + Name = GlobalSettings.UmbracoMigrationName, + Version = UmbracoVersion.GetSemanticVersion().ToString(), + CreateDate = DateTime.Now + }; + + _database.Insert("umbracoMigration", "pk", false, dto); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddUniqueIdPropertyTypeColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddUniqueIdPropertyTypeColumn.cs index f2f9261f52..58278eff84 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddUniqueIdPropertyTypeColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddUniqueIdPropertyTypeColumn.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero { + [Migration("7.3.0", 13, GlobalSettings.UmbracoMigrationName)] public class AddUniqueIdPropertyTypeColumn : MigrationBase { @@ -35,13 +36,17 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe // the already existing data, see: http://issues.umbraco.org/issue/U4-6942 foreach (var data in Context.Database.Query(@" -SELECT cmsPropertyType.id ptId, cmsPropertyType.Alias ptAlias, cmsContentType.alias ctAlias +SELECT cmsPropertyType.id ptId, cmsPropertyType.Alias ptAlias, cmsContentType.alias ctAlias, umbracoNode.nodeObjectType nObjType FROM cmsPropertyType INNER JOIN cmsContentType -ON cmsPropertyType.contentTypeId = cmsContentType.nodeId")) +ON cmsPropertyType.contentTypeId = cmsContentType.nodeId +INNER JOIN umbracoNode +ON cmsContentType.nodeId = umbracoNode.id")) { - //create a guid from the concatenation of the property type alias + the doc type alias - string concatAlias = data.ptAlias + data.ctAlias; + //create a guid from the concatenation of the: + // property type alias + the doc type alias + the content type node object type + // - the latter is required because there can be a content type and media type with the same alias!! + string concatAlias = data.ptAlias + data.ctAlias + data.nObjType; var ptGuid = concatAlias.ToGuid(); //set the Unique Id to the one we've generated diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs index 55095e1f8e..ac7e410a8f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs @@ -307,7 +307,7 @@ namespace Umbraco.Core.Persistence.Repositories .Append(new Sql(") tmpTbl LEFT JOIN (")) .Append(joinSql) .Append(new Sql(") as property ON id = property.contentNodeId")) - .OrderBy("sortOrder"); + .OrderBy("sortOrder, id"); return wrappedSql; } diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 5b9c8903c6..6aadbd269a 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -1,5 +1,7 @@ using System; +using System.Diagnostics; using System.Linq; +using System.Reflection; using System.Web; using System.Web.Hosting; using log4net; @@ -180,7 +182,47 @@ namespace Umbraco.Core { if (SystemUtilities.GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted) { - Logger.Info("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason); + //Try to log the detailed shutdown message (typical asp.net hack: http://weblogs.asp.net/scottgu/433194) + try + { + var runtime = (HttpRuntime)typeof(HttpRuntime).InvokeMember("_theRuntime", + BindingFlags.NonPublic + | BindingFlags.Static + | BindingFlags.GetField, + null, + null, + null); + if (runtime == null) + return; + + var shutDownMessage = (string)runtime.GetType().InvokeMember("_shutDownMessage", + BindingFlags.NonPublic + | BindingFlags.Instance + | BindingFlags.GetField, + null, + runtime, + null); + + var shutDownStack = (string)runtime.GetType().InvokeMember("_shutDownStack", + BindingFlags.NonPublic + | BindingFlags.Instance + | BindingFlags.GetField, + null, + runtime, + null); + + var shutdownMsg = string.Format("{0}\r\n\r\n_shutDownMessage={1}\r\n\r\n_shutDownStack={2}", + HostingEnvironment.ShutdownReason, + shutDownMessage, + shutDownStack); + + Logger.Info("Application shutdown. Details: " + shutdownMsg); + } + catch (Exception) + { + //if for some reason that fails, then log the normal output + Logger.Info("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason); + } } OnApplicationEnd(sender, e); diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 39258f6b1a..bb30ea09b9 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -135,12 +135,12 @@ False ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll - - ..\packages\ImageProcessor.2.2.8.0\lib\net45\ImageProcessor.dll + + ..\packages\ImageProcessor.2.3.0.0\lib\net45\ImageProcessor.dll True - - ..\packages\ImageProcessor.Web.4.3.6.0\lib\net45\ImageProcessor.Web.dll + + ..\packages\ImageProcessor.Web.4.4.0.0\lib\net45\ImageProcessor.Web.dll True diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index efab0db7da..289aed138d 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -5,8 +5,8 @@ - - + + diff --git a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs index 714b79514d..730efd380b 100644 --- a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs @@ -85,7 +85,11 @@ namespace Umbraco.Web var instructions = batch.SelectMany(x => x.Instructions).ToArray(); batch.Clear(); if (instructions.Length == 0) return; + WriteInstructions(instructions); + } + private void WriteInstructions(RefreshInstruction[] instructions) + { var dto = new CacheInstructionDto { UtcStamp = DateTime.UtcNow, @@ -96,21 +100,25 @@ namespace Umbraco.Web ApplicationContext.DatabaseContext.Database.Insert(dto); } - protected ICollection GetBatch(bool ensureHttpContext) + protected ICollection GetBatch(bool create) { - var httpContext = UmbracoContext.Current == null ? null : UmbracoContext.Current.HttpContext; - if (httpContext == null) - { - if (ensureHttpContext) - throw new NotSupportedException("Cannot execute without a valid/current UmbracoContext with an HttpContext assigned."); - return null; - } + // try get the http context from the UmbracoContext, we do this because in the case we are launching an async + // thread and we know that the cache refreshers will execute, we will ensure the UmbracoContext and therefore we + // can get the http context from it + var httpContext = (UmbracoContext.Current == null ? null : UmbracoContext.Current.HttpContext) + // if this is null, it could be that an async thread is calling this method that we weren't aware of and the UmbracoContext + // wasn't ensured at the beginning of the thread. We can try to see if the HttpContext.Current is available which might be + // the case if the asp.net synchronization context has kicked in + ?? (HttpContext.Current == null ? null : new HttpContextWrapper(HttpContext.Current)); + + // if no context was found, return null - we cannot not batch + if (httpContext == null) return null; var key = typeof (BatchedDatabaseServerMessenger).Name; // no thread-safety here because it'll run in only 1 thread (request) at a time var batch = (ICollection)httpContext.Items[key]; - if (batch == null && ensureHttpContext) + if (batch == null && create) httpContext.Items[key] = batch = new List(); return batch; } @@ -124,11 +132,13 @@ namespace Umbraco.Web string json = null) { var batch = GetBatch(true); - if (batch == null) - throw new Exception("Failed to get a batch."); + var instructions = RefreshInstruction.GetInstructions(refresher, messageType, ids, idType, json); - batch.Add(new RefreshInstructionEnvelope(servers, refresher, - RefreshInstruction.GetInstructions(refresher, messageType, ids, idType, json))); + // batch if we can, else write to DB immediately + if (batch == null) + WriteInstructions(instructions.ToArray()); + else + batch.Add(new RefreshInstructionEnvelope(servers, refresher, instructions)); } } } \ No newline at end of file diff --git a/src/Umbraco.Web/BatchedWebServiceServerMessenger.cs b/src/Umbraco.Web/BatchedWebServiceServerMessenger.cs index 5fc3b48eee..63536ca9f7 100644 --- a/src/Umbraco.Web/BatchedWebServiceServerMessenger.cs +++ b/src/Umbraco.Web/BatchedWebServiceServerMessenger.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Web; using Umbraco.Core.Sync; namespace Umbraco.Web @@ -38,11 +39,19 @@ namespace Umbraco.Web protected override ICollection GetBatch(bool ensureHttpContext) { - var httpContext = UmbracoContext.Current == null ? null : UmbracoContext.Current.HttpContext; + //try get the http context from the UmbracoContext, we do this because in the case we are launching an async + // thread and we know that the cache refreshers will execute, we will ensure the UmbracoContext and therefore we + // can get the http context from it + var httpContext = (UmbracoContext.Current == null ? null : UmbracoContext.Current.HttpContext) + //if this is null, it could be that an async thread is calling this method that we weren't aware of and the UmbracoContext + // wasn't ensured at the beginning of the thread. We can try to see if the HttpContext.Current is available which might be + // the case if the asp.net synchronization context has kicked in + ?? (HttpContext.Current == null ? null : new HttpContextWrapper(HttpContext.Current)); + if (httpContext == null) { if (ensureHttpContext) - throw new NotSupportedException("Cannot execute without a valid/current UmbracoContext with an HttpContext assigned."); + throw new NotSupportedException("Cannot execute without a valid/current HttpContext assigned."); return null; }