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
///