#18793: Making session utilization an opt-in/opt-out feature

Work Item: 18793

--HG--
branch : 1.x
This commit is contained in:
Piotr Szmyd
2012-10-12 17:37:53 -07:00
parent 31d0a9dc38
commit cca88356d4
11 changed files with 94 additions and 18 deletions

View File

@@ -6,8 +6,10 @@ using System.Web.Routing;
using Autofac;
using Moq;
using NUnit.Framework;
using Orchard.Caching;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
using Orchard.Mvc;
using Orchard.Mvc.Routes;
using Orchard.Tests.Stubs;
@@ -36,6 +38,10 @@ namespace Orchard.Tests.Mvc.Routes {
rootBuilder.RegisterModule(new WorkContextModule());
rootBuilder.RegisterType<WorkContextAccessor>().As<IWorkContextAccessor>().InstancePerMatchingLifetimeScope("shell");
rootBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>();
rootBuilder.RegisterType<ExtensionManager>().As<IExtensionManager>();
rootBuilder.RegisterType<StubCacheManager>().As<ICacheManager>();
rootBuilder.RegisterType<StubAsyncTokenProvider>().As<IAsyncTokenProvider>();
rootBuilder.RegisterType<StubParallelCacheContext>().As<IParallelCacheContext>();
_rootContainer = rootBuilder.Build();

View File

@@ -2,6 +2,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using System.Web.SessionState;
namespace Orchard.Tests.Stubs {
public class StubHttpContext : HttpContextBase {
@@ -24,6 +25,9 @@ namespace Orchard.Tests.Stubs {
_hostHeader = hostHeader;
}
public override void SetSessionStateBehavior(SessionStateBehavior sessionStateBehavior) {
}
public override HttpRequestBase Request {
get { return new StubHttpRequest(this); }
}

View File

@@ -1,5 +1,6 @@
Name: Themes
AntiForgery: enabled
SessionState: required
Author: The Orchard Team
Website: http://orchardproject.net
Version: 1.5

View File

@@ -12,16 +12,22 @@ namespace Orchard.Themes.Preview {
public string GetPreviewTheme() {
var httpContext = _httpContextAccessor.Current();
return Convert.ToString(httpContext.Session[PreviewThemeKey]);
if (httpContext.Session != null) {
return Convert.ToString(httpContext.Session[PreviewThemeKey]);
}
return null;
}
public void SetPreviewTheme(string themeName) {
var httpContext = _httpContextAccessor.Current();
if (string.IsNullOrEmpty(themeName)) {
httpContext.Session.Remove(PreviewThemeKey);
}
else {
httpContext.Session[PreviewThemeKey] = themeName;
if (httpContext.Session != null) {
if (string.IsNullOrEmpty(themeName)) {
httpContext.Session.Remove(PreviewThemeKey);
}
else {
httpContext.Session[PreviewThemeKey] = themeName;
}
}
}
}

View File

@@ -28,6 +28,7 @@ namespace Orchard.Environment.Extensions.Folders {
private const string FeatureNameSection = "featurename";
private const string PrioritySection = "priority";
private const string FeaturesSection = "features";
private const string SessionStateSection = "sessionstate";
private readonly ICacheManager _cacheManager;
private readonly IWebSiteFolder _webSiteFolder;
@@ -116,7 +117,8 @@ namespace Orchard.Environment.Extensions.Folders {
Tags = GetValue(manifest, TagsSection),
AntiForgery = GetValue(manifest, AntiForgerySection),
Zones = GetValue(manifest, ZonesSection),
BaseTheme = GetValue(manifest, BaseThemeSection)
BaseTheme = GetValue(manifest, BaseThemeSection),
SessionState = GetValue(manifest, SessionStateSection)
};
extensionDescriptor.Features = GetFeaturesForExtension(manifest, extensionDescriptor);
@@ -202,6 +204,9 @@ namespace Orchard.Environment.Extensions.Folders {
case PrioritySection:
manifest.Add(PrioritySection, field[1]);
break;
case SessionStateSection:
manifest.Add(SessionStateSection, field[1]);
break;
case FeaturesSection:
manifest.Add(FeaturesSection, reader.ReadToEnd());
break;

View File

@@ -29,6 +29,7 @@ namespace Orchard.Environment.Extensions.Models {
public string AntiForgery { get; set; }
public string Zones { get; set; }
public string BaseTheme { get; set; }
public string SessionState { get; set; }
public IEnumerable<FeatureDescriptor> Features { get; set; }
}

View File

@@ -1,10 +1,12 @@
using System.Web.Routing;
using System.Web.SessionState;
namespace Orchard.Mvc.Routes {
public class RouteDescriptor {
public string Name { get; set; }
public int Priority { get; set; }
public RouteBase Route { get; set; }
public SessionStateBehavior SessionState { get; set; }
}
public class HttpRouteDescriptor : RouteDescriptor {

View File

@@ -1,9 +1,12 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Routing;
using System.Web.SessionState;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
namespace Orchard.Mvc.Routes {
public class RoutePublisher : IRoutePublisher {
@@ -11,16 +14,19 @@ namespace Orchard.Mvc.Routes {
private readonly ShellSettings _shellSettings;
private readonly IWorkContextAccessor _workContextAccessor;
private readonly IRunningShellTable _runningShellTable;
private readonly IExtensionManager _extensionManager;
public RoutePublisher(
RouteCollection routeCollection,
ShellSettings shellSettings,
IWorkContextAccessor workContextAccessor,
IRunningShellTable runningShellTable) {
IRunningShellTable runningShellTable,
IExtensionManager extensionManager) {
_routeCollection = routeCollection;
_shellSettings = shellSettings;
_workContextAccessor = workContextAccessor;
_runningShellTable = runningShellTable;
_extensionManager = extensionManager;
}
public void Publish(IEnumerable<RouteDescriptor> routes) {
@@ -58,10 +64,35 @@ namespace Orchard.Mvc.Routes {
// new routes are added
foreach (var routeDescriptor in routesArray) {
var shellRoute = new ShellRoute(routeDescriptor.Route, _shellSettings, _workContextAccessor, _runningShellTable){IsHttpRoute = routeDescriptor is HttpRouteDescriptor};
// Loading session state information.
var defaultSessionState = SessionStateBehavior.Default;
if(routeDescriptor.Route is Route) {
object extensionId;
var routeCasted = routeDescriptor.Route as Route;
if(routeCasted != null && routeCasted.Constraints != null && routeCasted.Constraints.TryGetValue("area", out extensionId)) {
var extensionDescriptor = _extensionManager.GetExtension(extensionId.ToString());
if(extensionDescriptor != null) {
// if session state is not define explicitly, use the one define for the extension
if(routeDescriptor.SessionState == SessionStateBehavior.Default) {
Enum.TryParse(extensionDescriptor.SessionState, true /*ignoreCase*/, out defaultSessionState);
}
}
}
}
// Route-level setting overrides module-level setting (from manifest).
var sessionStateBehavior = routeDescriptor.SessionState == SessionStateBehavior.Default ? defaultSessionState : routeDescriptor.SessionState ;
var shellRoute = new ShellRoute(routeDescriptor.Route, _shellSettings, _workContextAccessor, _runningShellTable) {
IsHttpRoute = routeDescriptor is HttpRouteDescriptor,
SessionState = sessionStateBehavior
};
_routeCollection.Add(routeDescriptor.Name, shellRoute);
}
}
}
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Diagnostics;
using System.Web;
using System.Web.Http.WebHost;
using System.Web.Http.WebHost.Routing;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
@@ -30,6 +28,8 @@ namespace Orchard.Mvc.Routes {
Area = route.GetAreaName();
}
public SessionStateBehavior SessionState { get; set; }
public string ShellSettingsName { get { return _shellSettings.Name; } }
public string Area { get; private set; }
public bool IsHttpRoute { get; set; }
@@ -50,8 +50,11 @@ namespace Orchard.Mvc.Routes {
if (routeData == null)
return null;
// push provided session state behavior to underlying MvcHandler
effectiveHttpContext.SetSessionStateBehavior(SessionState);
// otherwise wrap handler and return it
routeData.RouteHandler = new RouteHandler(_workContextAccessor, routeData.RouteHandler);
routeData.RouteHandler = new RouteHandler(_workContextAccessor, routeData.RouteHandler, SessionState);
routeData.DataTokens["IWorkContextAccessor"] = _workContextAccessor;
if (IsHttpRoute) {
@@ -87,14 +90,17 @@ namespace Orchard.Mvc.Routes {
class RouteHandler : IRouteHandler {
private readonly IWorkContextAccessor _workContextAccessor;
private readonly IRouteHandler _routeHandler;
private readonly SessionStateBehavior _sessionStateBehavior;
public RouteHandler(IWorkContextAccessor workContextAccessor, IRouteHandler routeHandler) {
public RouteHandler(IWorkContextAccessor workContextAccessor, IRouteHandler routeHandler, SessionStateBehavior sessionStateBehavior) {
_workContextAccessor = workContextAccessor;
_routeHandler = routeHandler;
_sessionStateBehavior = sessionStateBehavior;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
var httpHandler = _routeHandler.GetHttpHandler(requestContext);
requestContext.HttpContext.SetSessionStateBehavior(_sessionStateBehavior);
if (httpHandler is IHttpAsyncHandler) {
return new HttpAsyncHandler(_workContextAccessor, (IHttpAsyncHandler)httpHandler);

View File

@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Mvc.Routes {
@@ -15,14 +17,19 @@ namespace Orchard.Mvc.Routes {
public IEnumerable<RouteDescriptor> GetRoutes() {
var displayPathsPerArea = _blueprint.Controllers.GroupBy(
x => x.AreaName,
x => x.Feature.Descriptor.Extension.Path);
x => x.Feature.Descriptor.Extension);
foreach (var item in displayPathsPerArea) {
var areaName = item.Key;
var displayPath = item.Distinct().Single();
var extensionDescriptor = item.Distinct().Single();
var displayPath = extensionDescriptor.Path;
SessionStateBehavior defaultSessionState;
Enum.TryParse(extensionDescriptor.SessionState, true /*ignoreCase*/, out defaultSessionState);
yield return new RouteDescriptor {
Priority = -10,
SessionState = defaultSessionState,
Route = new Route(
"Admin/" + displayPath + "/{action}/{id}",
new RouteValueDictionary {
@@ -37,8 +44,10 @@ namespace Orchard.Mvc.Routes {
},
new MvcRouteHandler())
};
yield return new RouteDescriptor {
Priority = -10,
SessionState = defaultSessionState == SessionStateBehavior.Default ? SessionStateBehavior.Disabled : defaultSessionState, // sessions are disabled by default on front-end
Route = new Route(
displayPath + "/{controller}/{action}/{id}",
new RouteValueDictionary {
@@ -60,6 +69,5 @@ namespace Orchard.Mvc.Routes {
foreach (var routeDescriptor in GetRoutes())
routes.Add(routeDescriptor);
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Web;
using System.Web.SessionState;
using Orchard.Mvc.Wrappers;
namespace Orchard.Mvc.Routes {
@@ -16,6 +17,11 @@ namespace Orchard.Mvc.Routes {
}
}
public override void SetSessionStateBehavior(SessionStateBehavior sessionStateBehavior)
{
_httpContextBase.SetSessionStateBehavior(sessionStateBehavior);
}
class AdjustedRequest : HttpRequestBaseWrapper {
private readonly UrlPrefix _prefix;