diff --git a/src/Umbraco.Web/Editors/MacroController.cs b/src/Umbraco.Web/Editors/MacroController.cs index aed6cec602..b0b2cb4bf2 100644 --- a/src/Umbraco.Web/Editors/MacroController.cs +++ b/src/Umbraco.Web/Editors/MacroController.cs @@ -4,21 +4,26 @@ using System.Net; using System.Net.Http; using System.Text; using System.Web.Http; +using System.Web.SessionState; using AutoMapper; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using umbraco; +using Umbraco.Core; namespace Umbraco.Web.Editors { /// /// API controller to deal with Macro data /// + /// + /// Note that this implements IRequiresSessionState which will enable HttpContext.Session - generally speaking we don't normally + /// enable this for webapi controllers, however since this controller is used to render macro content and macros can access + /// Session, we don't want it to throw null reference exceptions. + /// [PluginController("UmbracoApi")] - public class MacroController : UmbracoAuthorizedJsonController + public class MacroController : UmbracoAuthorizedJsonController, IRequiresSessionState { - - /// /// Gets the macro parameters to be filled in for a particular macro /// @@ -124,6 +129,6 @@ namespace Umbraco.Web.Editors "text/html"); return result; } - + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index 982286c24b..f1c27ffb96 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; +using System.Web.SessionState; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc { @@ -93,6 +95,13 @@ namespace Umbraco.Web.Mvc } //look in this namespace to create the controller controllerPluginRoute.DataTokens.Add("Namespaces", new[] {controllerType.Namespace}); + + //Special case! Check if the controller type implements IRequiresSessionState and if so use our + //custom webapi session handler + if (typeof(IRequiresSessionState).IsAssignableFrom(controllerType)) + { + controllerPluginRoute.RouteHandler = new SessionHttpControllerRouteHandler(); + } } //Don't look anywhere else except this namespace! @@ -100,9 +109,9 @@ namespace Umbraco.Web.Mvc //constraints: only match controllers ending with 'controllerSuffixName' and only match this controller's ID for this route if (controllerSuffixName.IsNullOrWhiteSpace() == false) - { - controllerPluginRoute.Constraints = new RouteValueDictionary( - new Dictionary + { + controllerPluginRoute.Constraints = new RouteValueDictionary( + new Dictionary { {"controller", @"(\w+)" + controllerSuffixName} }); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 31aa38b1bf..f756181cc4 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -956,6 +956,7 @@ + diff --git a/src/Umbraco.Web/WebApi/SessionHttpControllerRouteHandler.cs b/src/Umbraco.Web/WebApi/SessionHttpControllerRouteHandler.cs new file mode 100644 index 0000000000..d4d462c5f8 --- /dev/null +++ b/src/Umbraco.Web/WebApi/SessionHttpControllerRouteHandler.cs @@ -0,0 +1,31 @@ +using System.Web; +using System.Web.Http.WebHost; +using System.Web.Routing; +using System.Web.SessionState; + +namespace Umbraco.Web.WebApi +{ + /// + /// A custom WebApi route handler that enables session on the HttpContext - use with caution! + /// + /// + /// WebApi controllers (and REST in general) shouldn't have session state enabled since it's stateless, + /// enabling session state puts additional locks on requests so only use this when absolutley needed + /// + internal class SessionHttpControllerRouteHandler : HttpControllerRouteHandler + { + protected override IHttpHandler GetHttpHandler(RequestContext requestContext) + { + return new SessionHttpControllerHandler(requestContext.RouteData); + } + + /// + /// A custom WebApi handler that enables session on the HttpContext + /// + private class SessionHttpControllerHandler : HttpControllerHandler, IRequiresSessionState + { + public SessionHttpControllerHandler(RouteData routeData) : base(routeData) + { } + } + } +} \ No newline at end of file