diff --git a/src/Umbraco.Core/Constants-Web.cs b/src/Umbraco.Core/Constants-Web.cs index 60fba0ae40..f596820506 100644 --- a/src/Umbraco.Core/Constants-Web.cs +++ b/src/Umbraco.Core/Constants-Web.cs @@ -10,6 +10,12 @@ namespace Umbraco.Core /// public static class Web { + public const string UmbracoContextDataToken = "umbraco-context"; + public const string UmbracoDataToken = "umbraco"; + public const string PublishedDocumentRequestDataToken = "umbraco-doc-request"; + public const string CustomRouteDataToken = "umbraco-custom-route"; + public const string UmbracoRouteDefinitionDataToken = "umbraco-route-def"; + /// /// The preview cookie name /// diff --git a/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs index 0286a5bd0f..29a76b29d2 100644 --- a/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs @@ -165,7 +165,7 @@ namespace Umbraco.Tests.Mvc }; var routeData = new RouteData(); - routeData.DataTokens.Add("umbraco-route-def", routeDefinition); + routeData.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken, routeDefinition); var ctrl = new TestSurfaceController(umbCtx, new UmbracoHelper()); ctrl.ControllerContext = new ControllerContext(contextBase, routeData, ctrl); diff --git a/src/Umbraco.Tests/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Mvc/UmbracoViewPageTests.cs index ed6cc9b4eb..5f80909da9 100644 --- a/src/Umbraco.Tests/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Mvc/UmbracoViewPageTests.cs @@ -445,7 +445,7 @@ namespace Umbraco.Tests.Mvc var context = new ViewContext(); context.RouteData = new RouteData(); - context.RouteData.DataTokens.Add("umbraco-context", umbracoContext); + context.RouteData.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoContextDataToken, umbracoContext); return context; } diff --git a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs index b4171add35..10d105883f 100644 --- a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs +++ b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs @@ -124,7 +124,7 @@ namespace Umbraco.Web.Macros var routeVals = new RouteData(); routeVals.Values.Add("controller", "PartialViewMacro"); routeVals.Values.Add("action", "Index"); - routeVals.DataTokens.Add("umbraco-context", umbCtx); //required for UmbracoViewPage + routeVals.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoContextDataToken, umbCtx); //required for UmbracoViewPage //lets render this controller as a child action var viewContext = new ViewContext {ViewData = new ViewDataDictionary()};; diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index 2836c458fb..982286c24b 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -110,7 +110,7 @@ namespace Umbraco.Web.Mvc //match this area controllerPluginRoute.DataTokens.Add("area", area.AreaName); - controllerPluginRoute.DataTokens.Add("umbraco", umbracoTokenValue); //ensure the umbraco token is set + controllerPluginRoute.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, umbracoTokenValue); //ensure the umbraco token is set return controllerPluginRoute; } diff --git a/src/Umbraco.Web/Mvc/ControllerContextExtensions.cs b/src/Umbraco.Web/Mvc/ControllerContextExtensions.cs new file mode 100644 index 0000000000..c998ed931e --- /dev/null +++ b/src/Umbraco.Web/Mvc/ControllerContextExtensions.cs @@ -0,0 +1,50 @@ +using System.Web.Mvc; + +namespace Umbraco.Web.Mvc +{ + public static class ControllerContextExtensions + { + /// + /// Tries to get the Umbraco context from the whole ControllerContext hierarchy based on data tokens and if that fails + /// it will attempt to fallback to retrieving it from the HttpContext. + /// + /// + /// + public static UmbracoContext GetUmbracoContext(this ControllerContext controllerContext) + { + var umbCtx = controllerContext.RouteData.GetUmbracoContext(); + if (umbCtx != null) return umbCtx; + + if (controllerContext.ParentActionViewContext != null) + { + //recurse + return controllerContext.ParentActionViewContext.GetUmbracoContext(); + } + + //fallback to getting from HttpContext + return controllerContext.HttpContext.GetUmbracoContext(); + } + + /// + /// Find a data token in the whole ControllerContext hierarchy of execution + /// + /// + /// + /// + internal static object GetDataTokenInViewContextHierarchy(this ControllerContext controllerContext, string dataTokenName) + { + if (controllerContext.RouteData.DataTokens.ContainsKey(dataTokenName)) + { + return controllerContext.RouteData.DataTokens[dataTokenName]; + } + + if (controllerContext.ParentActionViewContext != null) + { + //recurse! + return controllerContext.ParentActionViewContext.GetDataTokenInViewContextHierarchy(dataTokenName); + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/ControllerExtensions.cs b/src/Umbraco.Web/Mvc/ControllerExtensions.cs index c15520b57c..734e60e8f5 100644 --- a/src/Umbraco.Web/Mvc/ControllerExtensions.cs +++ b/src/Umbraco.Web/Mvc/ControllerExtensions.cs @@ -5,24 +5,8 @@ using System.Web.Mvc; namespace Umbraco.Web.Mvc { - internal static class ControllerExtensions + internal static class ControllerExtensions { - internal static object GetDataTokenInViewContextHierarchy(this ControllerContext controllerContext, string dataTokenName) - { - if (controllerContext.RouteData.DataTokens.ContainsKey(dataTokenName)) - { - return controllerContext.RouteData.DataTokens[dataTokenName]; - } - - if (controllerContext.ParentActionViewContext != null) - { - //recurse! - return controllerContext.ParentActionViewContext.GetDataTokenInViewContextHierarchy(dataTokenName); - } - - return null; - } - /// /// Return the controller name from the controller type /// diff --git a/src/Umbraco.Web/Mvc/RenderModelBinder.cs b/src/Umbraco.Web/Mvc/RenderModelBinder.cs index ed81959fbd..f8e7ee8a4e 100644 --- a/src/Umbraco.Web/Mvc/RenderModelBinder.cs +++ b/src/Umbraco.Web/Mvc/RenderModelBinder.cs @@ -19,15 +19,19 @@ namespace Umbraco.Web.Mvc public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { object model; - if (controllerContext.RouteData.DataTokens.TryGetValue("umbraco", out model) == false) + if (controllerContext.RouteData.DataTokens.TryGetValue(Core.Constants.Web.UmbracoDataToken, out model) == false) return null; + //default culture var culture = CultureInfo.CurrentCulture; - // bind the model (use context culture as default, if available) - if (UmbracoContext.Current != null - && UmbracoContext.Current.PublishedContentRequest != null - && UmbracoContext.Current.PublishedContentRequest.Culture != null) - culture = UmbracoContext.Current.PublishedContentRequest.Culture; + + var umbracoContext = controllerContext.GetUmbracoContext() + ?? UmbracoContext.Current; + + if (umbracoContext != null && umbracoContext.PublishedContentRequest != null) + { + culture = umbracoContext.PublishedContentRequest.Culture; + } return BindModel(model, bindingContext.ModelType, culture); } diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index dd06b3ced1..f3886d8ce1 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -59,11 +59,11 @@ namespace Umbraco.Web.Mvc { if (_publishedContentRequest != null) return _publishedContentRequest; - if (RouteData.DataTokens.ContainsKey("umbraco-doc-request") == false) + if (RouteData.DataTokens.ContainsKey(Core.Constants.Web.PublishedDocumentRequestDataToken) == false) { throw new InvalidOperationException("DataTokens must contain an 'umbraco-doc-request' key with a PublishedContentRequest object"); } - _publishedContentRequest = (PublishedContentRequest)RouteData.DataTokens["umbraco-doc-request"]; + _publishedContentRequest = (PublishedContentRequest)RouteData.DataTokens[Core.Constants.Web.PublishedDocumentRequestDataToken]; return _publishedContentRequest; } } diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index bce3515c1b..d7ce36b4a4 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -97,9 +97,9 @@ namespace Umbraco.Web.Mvc internal void SetupRouteDataForRequest(RenderModel renderModel, RequestContext requestContext, PublishedContentRequest docRequest) { //put essential data into the data tokens, the 'umbraco' key is required to be there for the view engine - requestContext.RouteData.DataTokens.Add("umbraco", renderModel); //required for the RenderModelBinder and view engine - requestContext.RouteData.DataTokens.Add("umbraco-doc-request", docRequest); //required for RenderMvcController - requestContext.RouteData.DataTokens.Add("umbraco-context", UmbracoContext); //required for UmbracoTemplatePage + requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, renderModel); //required for the RenderModelBinder and view engine + requestContext.RouteData.DataTokens.Add(Core.Constants.Web.PublishedDocumentRequestDataToken, docRequest); //required for RenderMvcController + requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, UmbracoContext); //required for UmbracoTemplatePage } private void UpdateRouteDataForRequest(RenderModel renderModel, RequestContext requestContext) @@ -107,7 +107,7 @@ namespace Umbraco.Web.Mvc if (renderModel == null) throw new ArgumentNullException("renderModel"); if (requestContext == null) throw new ArgumentNullException("requestContext"); - requestContext.RouteData.DataTokens["umbraco"] = renderModel; + requestContext.RouteData.DataTokens[Core.Constants.Web.UmbracoDataToken] = renderModel; // the rest should not change -- it's only the published content that has changed } @@ -337,7 +337,7 @@ namespace Umbraco.Web.Mvc } //store the route definition - requestContext.RouteData.DataTokens["umbraco-route-def"] = def; + requestContext.RouteData.DataTokens[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken] = def; return def; } diff --git a/src/Umbraco.Web/Mvc/RenderViewEngine.cs b/src/Umbraco.Web/Mvc/RenderViewEngine.cs index ed7b941580..fdf61059e0 100644 --- a/src/Umbraco.Web/Mvc/RenderViewEngine.cs +++ b/src/Umbraco.Web/Mvc/RenderViewEngine.cs @@ -93,7 +93,7 @@ namespace Umbraco.Web.Mvc /// private bool ShouldFindView(ControllerContext controllerContext, bool isPartial) { - var umbracoToken = controllerContext.GetDataTokenInViewContextHierarchy("umbraco"); + var umbracoToken = controllerContext.GetDataTokenInViewContextHierarchy(Core.Constants.Web.UmbracoDataToken); //first check if we're rendering a partial view for the back office, or surface controller, etc... //anything that is not IUmbracoRenderModel as this should only pertain to Umbraco views. diff --git a/src/Umbraco.Web/Mvc/RouteValueDictionaryExtensions.cs b/src/Umbraco.Web/Mvc/RouteValueDictionaryExtensions.cs index 445441aafa..ceb4012a66 100644 --- a/src/Umbraco.Web/Mvc/RouteValueDictionaryExtensions.cs +++ b/src/Umbraco.Web/Mvc/RouteValueDictionaryExtensions.cs @@ -32,7 +32,7 @@ namespace Umbraco.Web.Mvc public static object GetRequiredObject(this RouteValueDictionary items, string key) { if (key == null) throw new ArgumentNullException("key"); - if (!items.Keys.Contains(key)) + if (items.Keys.Contains(key) == false) throw new ArgumentNullException("The " + key + " parameter was not found but is required"); return items[key]; } diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index 817ed97902..420573d745 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -185,9 +185,9 @@ namespace Umbraco.Web.Mvc while (currentContext != null) { var currentRouteData = currentContext.RouteData; - if (currentRouteData.DataTokens.ContainsKey("umbraco-route-def")) + if (currentRouteData.DataTokens.ContainsKey(Core.Constants.Web.UmbracoRouteDefinitionDataToken)) { - return Attempt.Succeed((RouteDefinition)currentRouteData.DataTokens["umbraco-route-def"]); + return Attempt.Succeed((RouteDefinition)currentRouteData.DataTokens[Core.Constants.Web.UmbracoRouteDefinitionDataToken]); } if (currentContext.IsChildAction) { diff --git a/src/Umbraco.Web/Mvc/SurfaceControllerFactory.cs b/src/Umbraco.Web/Mvc/SurfaceControllerFactory.cs index c82c59db65..8af018e833 100644 --- a/src/Umbraco.Web/Mvc/SurfaceControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/SurfaceControllerFactory.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Mvc return false; //ensure there is an umbraco token set - var umbracoToken = request.RouteData.DataTokens["umbraco"]; + var umbracoToken = request.RouteData.DataTokens[Core.Constants.Web.UmbracoDataToken]; if (umbracoToken == null || string.IsNullOrWhiteSpace(umbracoToken.ToString())) return false; diff --git a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs b/src/Umbraco.Web/Mvc/UmbracoPageResult.cs index f23515c1d9..da4cb198ac 100644 --- a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs +++ b/src/Umbraco.Web/Mvc/UmbracoPageResult.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web.Mvc ValidateRouteData(context.RouteData); - var routeDef = (RouteDefinition)context.RouteData.DataTokens["umbraco-route-def"]; + var routeDef = (RouteDefinition)context.RouteData.DataTokens[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken]; //Special case, if it is webforms but we're posting to an MVC surface controller, then we // need to return the webforms result instead @@ -91,7 +91,7 @@ namespace Umbraco.Web.Mvc /// private static void ValidateRouteData(RouteData routeData) { - if (routeData.DataTokens.ContainsKey("umbraco-route-def") == false) + if (routeData.DataTokens.ContainsKey(Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken) == false) { throw new InvalidOperationException("Can only use " + typeof(UmbracoPageResult).Name + " in the context of an Http POST when using a SurfaceController form"); diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 562ef8542e..861b872275 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -27,24 +27,13 @@ namespace Umbraco.Web.Mvc get { //we should always try to return the context from the data tokens just in case its a custom context and not - //using the UmbracoContext.Current. - //we will fallback to the singleton if necessary. - if (ViewContext.RouteData.DataTokens.ContainsKey("umbraco-context")) - { - return (UmbracoContext)ViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-context"); - } - //next check if it is a child action and see if the parent has it set in data tokens - if (ViewContext.IsChildAction) - { - if (ViewContext.ParentActionViewContext.RouteData.DataTokens.ContainsKey("umbraco-context")) - { - return (UmbracoContext)ViewContext.ParentActionViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-context"); - } - } - - //lastly, we will use the singleton, the only reason this should ever happen is is someone is rendering a page that inherits from this - //class and are rendering it outside of the normal Umbraco routing process. Very unlikely. - return UmbracoContext.Current; + //using the UmbracoContext.Current, we will fallback to the singleton if necessary. + var umbCtx = ViewContext.GetUmbracoContext() + //lastly, we will use the singleton, the only reason this should ever happen is is someone is rendering a page that inherits from this + //class and are rendering it outside of the normal Umbraco routing process. Very unlikely. + ?? UmbracoContext.Current; + + return umbCtx; } } @@ -66,16 +55,16 @@ namespace Umbraco.Web.Mvc //we should always try to return the object from the data tokens just in case its a custom object and not //using the UmbracoContext.Current. //we will fallback to the singleton if necessary. - if (ViewContext.RouteData.DataTokens.ContainsKey("umbraco-doc-request")) + if (ViewContext.RouteData.DataTokens.ContainsKey(Core.Constants.Web.PublishedDocumentRequestDataToken)) { - return (PublishedContentRequest)ViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-doc-request"); + return (PublishedContentRequest)ViewContext.RouteData.DataTokens.GetRequiredObject(Core.Constants.Web.PublishedDocumentRequestDataToken); } //next check if it is a child action and see if the parent has it set in data tokens if (ViewContext.IsChildAction) { - if (ViewContext.ParentActionViewContext.RouteData.DataTokens.ContainsKey("umbraco-doc-request")) + if (ViewContext.ParentActionViewContext.RouteData.DataTokens.ContainsKey(Core.Constants.Web.PublishedDocumentRequestDataToken)) { - return (PublishedContentRequest)ViewContext.ParentActionViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-doc-request"); + return (PublishedContentRequest)ViewContext.ParentActionViewContext.RouteData.DataTokens.GetRequiredObject(Core.Constants.Web.PublishedDocumentRequestDataToken); } } diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs index feb5b30ce2..5c948d2e0b 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; +using System.Web.Security; +using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Web.Models; using Umbraco.Web.Routing; @@ -19,7 +21,8 @@ namespace Umbraco.Web.Mvc if (found == null) return new NotFoundHandler(); umbracoContext.PublishedContentRequest = new PublishedContentRequest( - umbracoContext.CleanedUmbracoUrl, umbracoContext.RoutingContext) + umbracoContext.CleanedUmbracoUrl, umbracoContext.RoutingContext, + UmbracoConfig.For.UmbracoSettings().WebRouting, s => Roles.Provider.GetRolesForUser(s)) { PublishedContent = found }; @@ -31,11 +34,11 @@ namespace Umbraco.Web.Mvc var renderModel = new RenderModel(umbracoContext.PublishedContentRequest.PublishedContent, umbracoContext.PublishedContentRequest.Culture); //assigns the required tokens to the request - requestContext.RouteData.DataTokens.Add("umbraco", renderModel); - requestContext.RouteData.DataTokens.Add("umbraco-doc-request", umbracoContext.PublishedContentRequest); - requestContext.RouteData.DataTokens.Add("umbraco-context", umbracoContext); + requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, renderModel); + requestContext.RouteData.DataTokens.Add(Core.Constants.Web.PublishedDocumentRequestDataToken, umbracoContext.PublishedContentRequest); + requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbracoContext); //this is used just for a flag that this is an umbraco custom route - requestContext.RouteData.DataTokens.Add("umbraco-custom-route", true); + requestContext.RouteData.DataTokens.Add(Core.Constants.Web.CustomRouteDataToken, true); //Here we need to detect if a SurfaceController has posted var formInfo = RenderRouteHandler.GetFormInfo(requestContext); @@ -49,7 +52,7 @@ namespace Umbraco.Web.Mvc }; //set the special data token to the current route definition - requestContext.RouteData.DataTokens["umbraco-route-def"] = def; + requestContext.RouteData.DataTokens[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken] = def; return RenderRouteHandler.HandlePostedValues(requestContext, formInfo); } diff --git a/src/Umbraco.Web/RouteDataExtensions.cs b/src/Umbraco.Web/RouteDataExtensions.cs new file mode 100644 index 0000000000..5d7f513ad6 --- /dev/null +++ b/src/Umbraco.Web/RouteDataExtensions.cs @@ -0,0 +1,28 @@ +using System; +using System.Web.Routing; + +namespace Umbraco.Web +{ + public static class RouteDataExtensions + { + /// + /// Tries to get the Umbraco context from the DataTokens + /// + /// + /// + /// + /// This is useful when working on async threads since the UmbracoContext is not copied over explicitly + /// + public static UmbracoContext GetUmbracoContext(this RouteData routeData) + { + if (routeData == null) throw new ArgumentNullException("routeData"); + + if (routeData.DataTokens.ContainsKey(UmbracoContext.HttpContextItemName)) + { + var umbCtx = routeData.DataTokens[UmbracoContext.HttpContextItemName] as UmbracoContext; + return umbCtx; + } + return null; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs b/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs index 2bb2903aa0..989cabe388 100644 --- a/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs +++ b/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Routing if (umbracoContext.HttpContext.Request.RequestContext == null) return null; if (umbracoContext.HttpContext.Request.RequestContext.RouteData == null) return null; if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens == null) return null; - if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey("umbraco-custom-route") == false) return null; + if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey(Umbraco.Core.Constants.Web.CustomRouteDataToken) == false) return null; //ok so it's a custom route with published content assigned, check if the id being requested for is the same id as the assigned published content return id == umbracoContext.PublishedContentRequest.PublishedContent.Id ? umbracoContext.PublishedContentRequest.PublishedContent.Url diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 2c9542fe2d..e12afc0a65 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -341,6 +341,7 @@ + @@ -350,6 +351,7 @@ + diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 50788c4b2e..6bd325c275 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web /// public class UmbracoContext : DisposableObject, IDisposeOnRequestEnd { - private const string HttpContextItemName = "Umbraco.Web.UmbracoContext"; + internal const string HttpContextItemName = "Umbraco.Web.UmbracoContext"; private static readonly object Locker = new object(); private bool _replacing; diff --git a/src/Umbraco.Web/UmbracoContextExtensions.cs b/src/Umbraco.Web/UmbracoContextExtensions.cs index ec85b4dad6..8cd38df6d1 100644 --- a/src/Umbraco.Web/UmbracoContextExtensions.cs +++ b/src/Umbraco.Web/UmbracoContextExtensions.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Web; +using Umbraco.Core; using Umbraco.Core.Events; namespace Umbraco.Web @@ -11,6 +13,38 @@ namespace Umbraco.Web /// public static class UmbracoContextExtensions { + /// + /// tries to get the Umbraco context from the HttpContext + /// + /// + /// + /// + /// This is useful when working on async threads since the UmbracoContext is not copied over explicitly + /// + public static UmbracoContext GetUmbracoContext(this HttpContext http) + { + return GetUmbracoContext(new HttpContextWrapper(http)); + } + + /// + /// tries to get the Umbraco context from the HttpContext + /// + /// + /// + /// + /// This is useful when working on async threads since the UmbracoContext is not copied over explicitly + /// + public static UmbracoContext GetUmbracoContext(this HttpContextBase http) + { + if (http == null) throw new ArgumentNullException("http"); + + if (http.Items.Contains(UmbracoContext.HttpContextItemName)) + { + var umbCtx = http.Items[UmbracoContext.HttpContextItemName] as UmbracoContext; + return umbCtx; + } + return null; + } /// /// If there are event messages in the current request this will return them , otherwise it will return null diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index c4252223f3..42ef78d96e 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -338,7 +338,7 @@ namespace Umbraco.Web { route.DataTokens = new RouteValueDictionary(); } - route.DataTokens.Add("umbraco", "api"); //ensure the umbraco token is set + route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set } private void RouteLocalSurfaceController(Type controller, string umbracoPath) @@ -349,7 +349,7 @@ namespace Umbraco.Web umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}",//url to match new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional }, new[] { meta.ControllerNamespace }); //look in this namespace to create the controller - route.DataTokens.Add("umbraco", "surface"); //ensure the umbraco token is set + route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); //ensure the umbraco token is set route.DataTokens.Add("UseNamespaceFallback", false); //Don't look anywhere else except this namespace! //make it use our custom/special SurfaceMvcHandler route.RouteHandler = new SurfaceRouteHandler();