From c8b8b28e9b8f4b0a11bdcf1edc7cc27e7b393a0d Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Tue, 12 Mar 2013 00:10:59 +0400 Subject: [PATCH] applies patch for #U4-1890 --- src/Umbraco.Core/CoreBootManager.cs | 27 ++++++++-- src/Umbraco.Web/UmbracoContext.cs | 77 +++++++++++++++++++++++++++-- src/Umbraco.Web/UmbracoModule.cs | 18 +------ src/Umbraco.Web/WebBootManager.cs | 16 +++++- 4 files changed, 111 insertions(+), 27 deletions(-) diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index 75e54f6573..6110973949 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -60,9 +60,8 @@ namespace Umbraco.Core new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy()); - - //create the ApplicationContext - ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext); + + CreateApplicationContext(dbContext, serviceContext); InitializeApplicationEventsResolver(); @@ -80,6 +79,17 @@ namespace Umbraco.Core return this; } + /// + /// Creates and assigns the application context singleton + /// + /// + /// + protected virtual void CreateApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext) + { + //create the ApplicationContext + ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext); + } + /// /// Special method to initialize the ApplicationEventsResolver and any modifications required for it such /// as adding custom types to the resolver. @@ -133,8 +143,7 @@ namespace Umbraco.Core if (_isComplete) throw new InvalidOperationException("The boot manager has already been completed"); - //freeze resolution to not allow Resolvers to be modified - Resolution.Freeze(); + FreezeResolution(); //stop the timer and log the output _timer.Dispose(); @@ -159,6 +168,14 @@ namespace Umbraco.Core return this; } + /// + /// Freeze resolution to not allow Resolvers to be modified + /// + protected virtual void FreezeResolution() + { + Resolution.Freeze(); + } + /// /// Create the resolvers /// diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index eecfcc7ff4..86dbf76259 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -34,6 +34,47 @@ namespace Umbraco.Web /// private static UmbracoContext _umbracoContext; + /// + /// This is a helper method which is called to ensure that the singleton context is created and the nice url and routing + /// context is created and assigned. + /// + /// + /// + /// + /// The Singleton context object + /// + /// + /// This is created in order to standardize the creation of the singleton. Normally it is created during a request + /// in the UmbracoModule, however this module does not execute during application startup so we need to ensure it + /// during the startup process as well. + /// See: http://issues.umbraco.org/issue/U4-1890 + /// + internal static UmbracoContext EnsureContext(HttpContextBase httpContext, ApplicationContext applicationContext) + { + if (UmbracoContext.Current != null) + return UmbracoContext.Current; + + var umbracoContext = new UmbracoContext(httpContext, applicationContext, RoutesCacheResolver.Current.RoutesCache); + + // create the nice urls provider + var niceUrls = new NiceUrlProvider(PublishedContentStoreResolver.Current.PublishedContentStore, umbracoContext); + + // create the RoutingContext, and assign + var routingContext = new RoutingContext( + umbracoContext, + DocumentLookupsResolver.Current.DocumentLookups, + LastChanceLookupResolver.Current.LastChanceLookup, + PublishedContentStoreResolver.Current.PublishedContentStore, + niceUrls); + + //assign the routing context back + umbracoContext.RoutingContext = routingContext; + + //assign the singleton + UmbracoContext.Current = umbracoContext; + return UmbracoContext.Current; + } + /// /// Creates a new Umbraco context. /// @@ -57,7 +98,19 @@ namespace Umbraco.Web // set the urls... //original request url - this.OriginalRequestUrl = httpContext.Request.Url; + //NOTE: The request will not be available during app startup so we can only set this to an absolute URL of localhost, this + // is a work around to being able to access the UmbracoContext during application startup and this will also ensure that people + // 'could' still generate URLs during startup BUT any domain driven URL generation will not work because it is NOT possible to get + // the current domain during application startup. + // see: http://issues.umbraco.org/issue/U4-1890 + + var requestUrl = new Uri("http://localhost"); + var request = GetRequestFromContext(); + if (request != null) + { + requestUrl = request.Url; + } + this.OriginalRequestUrl = requestUrl; //cleaned request url this.CleanedUmbracoUrl = UriUtility.UriToUmbraco(this.OriginalRequestUrl); @@ -230,7 +283,10 @@ namespace Umbraco.Web { get { - return GlobalSettings.DebugMode && (!string.IsNullOrEmpty(HttpContext.Request["umbdebugshowtrace"]) || !string.IsNullOrEmpty(HttpContext.Request["umbdebug"])); + var request = GetRequestFromContext(); + //NOTE: the request can be null during app startup! + return GlobalSettings.DebugMode && request != null + && (!string.IsNullOrEmpty(request["umbdebugshowtrace"]) || !string.IsNullOrEmpty(request["umbdebug"])); } } @@ -273,10 +329,11 @@ namespace Umbraco.Web { get { - if (HttpContext.Request == null || HttpContext.Request.Url == null) + var request = GetRequestFromContext(); + if (request == null || request.Url == null) return false; - var currentUrl = HttpContext.Request.Url.AbsolutePath; + var currentUrl = request.Url.AbsolutePath; // zb-00004 #29956 : refactor cookies names & handling return StateHelper.Cookies.Preview.HasValue // has preview cookie @@ -285,6 +342,18 @@ namespace Umbraco.Web } } + private HttpRequestBase GetRequestFromContext() + { + try + { + return HttpContext.Request; + } + catch (System.Web.HttpException) + { + return null; + } + } + } } \ No newline at end of file diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 90ded62fd2..134f14353f 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -50,23 +50,7 @@ namespace Umbraco.Web legacyRequestInitializer.InitializeRequest(); // create the UmbracoContext singleton, one per request, and assign - var umbracoContext = new UmbracoContext( - httpContext, - ApplicationContext.Current, - RoutesCacheResolver.Current.RoutesCache); - UmbracoContext.Current = umbracoContext; - - // create the nice urls provider - var niceUrls = new NiceUrlProvider(PublishedContentStoreResolver.Current.PublishedContentStore, umbracoContext); - - // create the RoutingContext, and assign - var routingContext = new RoutingContext( - umbracoContext, - DocumentLookupsResolver.Current.DocumentLookups, - LastChanceLookupResolver.Current.LastChanceLookup, - PublishedContentStoreResolver.Current.PublishedContentStore, - niceUrls); - umbracoContext.RoutingContext = routingContext; + UmbracoContext.EnsureContext(httpContext, ApplicationContext.Current); } /// diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index 05caa0b0d0..c112fcf1d1 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Web; using System.Web.Mvc; using System.Web.Routing; using Umbraco.Core; @@ -51,7 +52,7 @@ namespace Umbraco.Web /// /// public override IBootManager Initialize() - { + { base.Initialize(); // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK] @@ -73,6 +74,19 @@ namespace Umbraco.Web return this; } + /// + /// Override this method in order to ensure that the UmbracoContext is also created, this can only be + /// created after resolution is frozen! + /// + protected override void FreezeResolution() + { + base.FreezeResolution(); + + //before we do anything, we'll ensure the umbraco context + //see: http://issues.umbraco.org/issue/U4-1717 + UmbracoContext.EnsureContext(new HttpContextWrapper(UmbracoApplication.Context), ApplicationContext); + } + /// /// Adds custom types to the ApplicationEventsResolver ///