Integrating routing work into project

Uncommenting old route collection publisher tests
Factoring wrapping handler into async and non-async cases
Adding [IContainerProvider] to datatokens at the time the routedata is matched

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-04-23 11:45:30 -07:00
parent ca222e60f7
commit 4b15c18ce0
3 changed files with 181 additions and 158 deletions

View File

@@ -1,109 +1,114 @@
//using System; using System;
//using System.Linq; using System.Linq;
//using System.Threading; using System.Threading;
//using System.Web.Mvc; using System.Web.Mvc;
//using System.Web.Routing; using System.Web.Routing;
//using NUnit.Framework; using Autofac;
//using Orchard.Mvc.Routes; using NUnit.Framework;
//using Orchard.Tests.Stubs; using Orchard.Environment.Configuration;
using Orchard.Mvc.Routes;
using Orchard.Tests.Stubs;
using Orchard.Tests.Utility;
//namespace Orchard.Tests.Mvc { namespace Orchard.Tests.Mvc {
// [TestFixture] [TestFixture]
// public class RouteCollectionPublisherTests { public class RouteCollectionPublisherTests {
// static RouteDescriptor Desc(string name, string url) { private IContainer _container;
// return new RouteDescriptor {Name = name, Route = new Route(url, new MvcRouteHandler())}; private RouteCollection _routes;
// }
// //[Test] static RouteDescriptor Desc(string name, string url) {
// //public void PublisherShouldReplaceRoutes() { return new RouteDescriptor { Name = name, Route = new Route(url, new MvcRouteHandler()) };
}
// // var routes = new RouteCollection(); [SetUp]
// // routes.MapRoute("foo", "{controller}"); public void Init() {
_routes = new RouteCollection();
// // IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null)); var builder = new ContainerBuilder();
// // publisher.Publish(new[] {Desc("barname", "bar"), Desc("quuxname", "quux")}); builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
builder.RegisterType<ShellRoute>().InstancePerDependency();
// // Assert.That(routes.Count(), Is.EqualTo(2)); builder.Register(ctx => _routes);
// //} builder.Register(ctx => new ShellSettings { Name = "Default" });
builder.RegisterAutoMocking();
// //[Test] _container = builder.Build();
// //public void RoutesCanHaveNullOrEmptyNames() { }
// // var routes = new RouteCollection();
// // routes.MapRoute("foo", "{controller}");
// // IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null));
// // publisher.Publish(new[] { Desc(null, "bar"), Desc(string.Empty, "quux") });
// // Assert.That(routes.Count(), Is.EqualTo(2));
// //}
// //[Test]
// //[ExpectedException(typeof(ArgumentException))]
// //public void SameNameTwiceCausesExplosion() {
// // var routes = new RouteCollection();
// // routes.MapRoute("foo", "{controller}");
// // IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null));
// // publisher.Publish(new[] {Desc("yarg", "bar"), Desc("yarg", "quux")});
// // Assert.That(routes.Count(), Is.EqualTo(2));
// //}
// [Test] [Test]
// public void ExplosionLeavesOriginalRoutesIntact() { public void PublisherShouldAddRoutesThenReplaceTheOnesWhichWereAdded() {
// var routes = new RouteCollection();
// routes.MapRoute("foo", "{controller}");
// IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null)); _routes.MapRoute("foo", "{controller}");
// try {
// publisher.Publish(new[] { Desc("yarg", "bar"), Desc("yarg", "quux") });
// }
// catch (ArgumentException) {
// Assert.That(routes.Count(), Is.EqualTo(1));
// Assert.That(routes.OfType<Route>().Single().Url, Is.EqualTo("{controller}"));
// }
// }
// [Test] var publisher = _container.Resolve<IRoutePublisher>();
// public void RoutesArePaintedWithConainerProviderAsTheyAreApplied() { publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") });
// var routes = new RouteCollection();
// routes.MapRoute("foo", "{controller}");
// var containerProvider = new StubContainerProvider(null, null); Assert.That(_routes.Count(), Is.EqualTo(3));
// IRoutePublisher publisher = new RoutePublisher(routes, containerProvider);
// publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") });
// Assert.That(routes.OfType<Route>().Count(), Is.EqualTo(2)); publisher.Publish(new[] { Desc("baazname", "baaz")});
// Assert.That(routes.OfType<Route>().SelectMany(r => r.DataTokens.Values).Count(), Is.EqualTo(2));
// Assert.That(routes.OfType<Route>().SelectMany(r => r.DataTokens.Values), Has.All.SameAs(containerProvider));
// }
// [Test] Assert.That(_routes.Count(), Is.EqualTo(2));
// public void WriteBlocksWhileReadIsInEffect() { }
// var routes = new RouteCollection();
// routes.MapRoute("foo", "{controller}");
// var containerProvider = new StubContainerProvider(null, null); [Test]
// IRoutePublisher publisher = new RoutePublisher(routes, containerProvider); public void RoutesCanHaveNullOrEmptyNames() {
_routes.MapRoute("foo", "{controller}");
// var readLock = routes.GetReadLock(); var publisher = _container.Resolve<IRoutePublisher>();
publisher.Publish(new[] { Desc(null, "bar"), Desc(string.Empty, "quux") });
// string where = "init"; Assert.That(_routes.Count(), Is.EqualTo(3));
// var action = new Action(() => { }
// where = "before";
// publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") }); [Test]
// where = "after"; [ExpectedException(typeof(ArgumentException))]
// }); public void SameNameTwiceCausesExplosion() {
_routes.MapRoute("foo", "{controller}");
var publisher = _container.Resolve<IRoutePublisher>();
publisher.Publish(new[] { Desc("yarg", "bar"), Desc("yarg", "quux") });
Assert.That(_routes.Count(), Is.EqualTo(2));
}
[Test]
public void ExplosionLeavesOriginalRoutesIntact() {
_routes.MapRoute("foo", "{controller}");
var publisher = _container.Resolve<IRoutePublisher>();
try {
publisher.Publish(new[] { Desc("yarg", "bar"), Desc("yarg", "quux") });
}
catch (ArgumentException) {
Assert.That(_routes.Count(), Is.EqualTo(1));
Assert.That(_routes.OfType<Route>().Single().Url, Is.EqualTo("{controller}"));
}
}
[Test]
public void WriteBlocksWhileReadIsInEffect() {
_routes.MapRoute("foo", "{controller}");
var publisher = _container.Resolve<IRoutePublisher>();
var readLock = _routes.GetReadLock();
string where = "init";
var action = new Action(() => {
where = "before";
publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") });
where = "after";
});
Assert.That(where, Is.EqualTo("init"));
var async = action.BeginInvoke(null, null);
Thread.Sleep(75);
Assert.That(where, Is.EqualTo("before"));
readLock.Dispose();
Thread.Sleep(75);
Assert.That(where, Is.EqualTo("after"));
action.EndInvoke(async);
}
}
}
// Assert.That(where, Is.EqualTo("init"));
// var async = action.BeginInvoke(null, null);
// Thread.Sleep(75);
// Assert.That(where, Is.EqualTo("before"));
// readLock.Dispose();
// Thread.Sleep(75);
// Assert.That(where, Is.EqualTo("after"));
// action.EndInvoke(async);
// }
// }
//}

View File

@@ -24,6 +24,32 @@ namespace Orchard.Tests.Mvc.Routes {
private ShellSettings _settingsB; private ShellSettings _settingsB;
private IContainer _rootContainer; private IContainer _rootContainer;
[SetUp]
public void Init() {
_settingsA = new ShellSettings { Name = "Alpha" };
_settingsB = new ShellSettings { Name = "Beta", };
_routes = new RouteCollection();
var rootBuilder = new ContainerBuilder();
rootBuilder.Register(ctx => _routes);
rootBuilder.RegisterType<ShellRoute>().InstancePerDependency();
rootBuilder.RegisterType<RunningShellTable>().As<IRunningShellTable>().SingleInstance();
_rootContainer = rootBuilder.Build();
_containerA = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsA);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
});
_containerB = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsB);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
});
}
[Test] [Test]
public void FactoryMethodWillCreateShellRoutes() { public void FactoryMethodWillCreateShellRoutes() {
var settings = new ShellSettings { Name = "Alpha" }; var settings = new ShellSettings { Name = "Alpha" };
@@ -52,33 +78,9 @@ namespace Orchard.Tests.Mvc.Routes {
Assert.That(route2.Area, Is.EqualTo("Beta")); Assert.That(route2.Area, Is.EqualTo("Beta"));
} }
private void Init() {
_settingsA = new ShellSettings {Name = "Alpha"};
_settingsB = new ShellSettings {Name = "Beta", };
_routes = new RouteCollection();
var rootBuilder = new ContainerBuilder();
rootBuilder.Register(ctx => _routes);
rootBuilder.RegisterType<ShellRoute>().InstancePerDependency();
rootBuilder.RegisterType<RunningShellTable>().As<IRunningShellTable>().SingleInstance();
_rootContainer = rootBuilder.Build();
_containerA = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsA);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
});
_containerB = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsB);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
});
}
[Test] [Test]
public void RoutePublisherReplacesOnlyNamedShellsRoutes() { public void RoutePublisherReplacesOnlyNamedShellsRoutes() {
Init();
var routeA = new Route("foo", new MvcRouteHandler()); var routeA = new Route("foo", new MvcRouteHandler());
var routeB = new Route("bar", new MvcRouteHandler()); var routeB = new Route("bar", new MvcRouteHandler());
@@ -108,17 +110,18 @@ namespace Orchard.Tests.Mvc.Routes {
[Test] [Test]
public void MatchingRouteToActiveShellTableWillLimitTheAbilityToMatchRoutes() { public void MatchingRouteToActiveShellTableWillLimitTheAbilityToMatchRoutes() {
Init();
var routeFoo = new Route("foo", new MvcRouteHandler()); var routeFoo = new Route("foo", new MvcRouteHandler());
_settingsA.RequestUrlHost = "a.example.com"; _settingsA.RequestUrlHost = "a.example.com";
_containerA.Resolve<IRoutePublisher>().Publish( _containerA.Resolve<IRoutePublisher>().Publish(
new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}}); new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}});
_rootContainer.Resolve<IRunningShellTable>().Add(_settingsA);
_settingsB.RequestUrlHost = "b.example.com"; _settingsB.RequestUrlHost = "b.example.com";
_containerB.Resolve<IRoutePublisher>().Publish( _containerB.Resolve<IRoutePublisher>().Publish(
new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}}); new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}});
_rootContainer.Resolve<IRunningShellTable>().Add(_settingsB);
var httpContext = new StubHttpContext("~/foo"); var httpContext = new StubHttpContext("~/foo");
var routeData = _routes.GetRouteData(httpContext); var routeData = _routes.GetRouteData(httpContext);
@@ -129,16 +132,16 @@ namespace Orchard.Tests.Mvc.Routes {
Assert.That(routeDataA, Is.Not.Null); Assert.That(routeDataA, Is.Not.Null);
Assert.That(routeDataA.DataTokens.ContainsKey("IContainerProvider"), Is.True); Assert.That(routeDataA.DataTokens.ContainsKey("IContainerProvider"), Is.True);
var routeContainerProviderA = (IContainerProvider)routeDataA.DataTokens["IContainerProvider"]; var routeContainerProviderA = (IContainerProvider)routeDataA.DataTokens["IContainerProvider"];
Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRouteProvider>(), Is.SameAs(_containerA.Resolve<IRouteProvider>())); Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRoutePublisher>(), Is.SameAs(_containerA.Resolve<IRoutePublisher>()));
Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRouteProvider>(), Is.Not.SameAs(_containerB.Resolve<IRouteProvider>())); Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRoutePublisher>(), Is.Not.SameAs(_containerB.Resolve<IRoutePublisher>()));
var httpContextB = new StubHttpContext("~/foo", "b.example.com"); var httpContextB = new StubHttpContext("~/foo", "b.example.com");
var routeDataB = _routes.GetRouteData(httpContextB); var routeDataB = _routes.GetRouteData(httpContextB);
Assert.That(routeDataB, Is.Not.Null); Assert.That(routeDataB, Is.Not.Null);
Assert.That(routeDataB.DataTokens.ContainsKey("IContainerProvider"), Is.True); Assert.That(routeDataB.DataTokens.ContainsKey("IContainerProvider"), Is.True);
var routeContainerProviderB = (IContainerProvider)routeDataA.DataTokens["IContainerProvider"]; var routeContainerProviderB = (IContainerProvider)routeDataB.DataTokens["IContainerProvider"];
Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRouteProvider>(), Is.SameAs(_containerB.Resolve<IRouteProvider>())); Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRoutePublisher>(), Is.SameAs(_containerB.Resolve<IRoutePublisher>()));
Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRouteProvider>(), Is.Not.SameAs(_containerA.Resolve<IRouteProvider>())); Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRoutePublisher>(), Is.Not.SameAs(_containerA.Resolve<IRoutePublisher>()));
} }
} }

View File

@@ -51,7 +51,9 @@ namespace Orchard.Mvc.Routes {
return null; return null;
// otherwise paint wrap handler and return it // otherwise paint wrap handler and return it
routeData.RouteHandler = new RouteHandler(_container, routeData.RouteHandler); var containerProvider = new ContainerProvider(_container);
routeData.RouteHandler = new RouteHandler(containerProvider, routeData.RouteHandler);
routeData.DataTokens["IContainerProvider"] = containerProvider;
return routeData; return routeData;
} }
@@ -66,33 +68,49 @@ namespace Orchard.Mvc.Routes {
return virtualPath; return virtualPath;
} }
class ContainerProvider : IContainerProvider {
public ContainerProvider(IContainer applicationContainer) {
ApplicationContainer = applicationContainer;
}
public void BeginRequestLifetime() {
RequestLifetime = ApplicationContainer.BeginLifetimeScope("httpRequest");
}
public void EndRequestLifetime() {
RequestLifetime.Dispose();
RequestLifetime = null;
}
public IContainer ApplicationContainer { get; set; }
public ILifetimeScope RequestLifetime { get; set; }
}
class RouteHandler : IRouteHandler { class RouteHandler : IRouteHandler {
private readonly IContainer _container; private readonly ContainerProvider _containerProvider;
private readonly IRouteHandler _routeHandler; private readonly IRouteHandler _routeHandler;
public RouteHandler(IContainer container, IRouteHandler routeHandler) { public RouteHandler(ContainerProvider containerProvider, IRouteHandler routeHandler) {
_container = container; _containerProvider = containerProvider;
_routeHandler = routeHandler; _routeHandler = routeHandler;
} }
public IHttpHandler GetHttpHandler(RequestContext requestContext) { public IHttpHandler GetHttpHandler(RequestContext requestContext) {
var httpHandler = _routeHandler.GetHttpHandler(requestContext); var httpHandler = _routeHandler.GetHttpHandler(requestContext);
return new HttpAsyncHandler( if (httpHandler is IHttpAsyncHandler) {
_container, return new HttpAsyncHandler(_containerProvider, (IHttpAsyncHandler)httpHandler);
requestContext, }
(IHttpAsyncHandler)httpHandler); return new HttpHandler(_containerProvider, httpHandler);
} }
} }
class HttpAsyncHandler : IHttpAsyncHandler, IRequiresSessionState, IContainerProvider { class HttpHandler : IHttpHandler, IRequiresSessionState {
private readonly RequestContext _requestContext; protected readonly ContainerProvider _containerProvider;
private readonly IHttpAsyncHandler _httpAsyncHandler; private readonly IHttpHandler _httpHandler;
public HttpAsyncHandler(IContainer applicationContainer, RequestContext requestContext, IHttpAsyncHandler httpAsyncHandler) { public HttpHandler(ContainerProvider containerProvider, IHttpHandler httpHandler) {
ApplicationContainer = applicationContainer; _containerProvider = containerProvider;
_requestContext = requestContext; _httpHandler = httpHandler;
_httpAsyncHandler = httpAsyncHandler;
} }
public bool IsReusable { public bool IsReusable {
@@ -100,22 +118,31 @@ namespace Orchard.Mvc.Routes {
} }
public void ProcessRequest(HttpContext context) { public void ProcessRequest(HttpContext context) {
BeginRequestLifetime(); _containerProvider.BeginRequestLifetime();
try { try {
_httpAsyncHandler.ProcessRequest(context); _httpHandler.ProcessRequest(context);
} }
finally { finally {
EndRequestLifetime(); _containerProvider.EndRequestLifetime();
}
} }
} }
class HttpAsyncHandler : HttpHandler, IHttpAsyncHandler {
private readonly IHttpAsyncHandler _httpAsyncHandler;
public HttpAsyncHandler(ContainerProvider containerProvider, IHttpAsyncHandler httpAsyncHandler)
: base(containerProvider, httpAsyncHandler) {
_httpAsyncHandler = httpAsyncHandler;
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {
BeginRequestLifetime(); _containerProvider.BeginRequestLifetime();
try { try {
return _httpAsyncHandler.BeginProcessRequest(context, cb, extraData); return _httpAsyncHandler.BeginProcessRequest(context, cb, extraData);
} }
catch { catch {
EndRequestLifetime(); _containerProvider.EndRequestLifetime();
throw; throw;
} }
} }
@@ -125,22 +152,10 @@ namespace Orchard.Mvc.Routes {
_httpAsyncHandler.EndProcessRequest(result); _httpAsyncHandler.EndProcessRequest(result);
} }
finally { finally {
EndRequestLifetime(); _containerProvider.EndRequestLifetime();
} }
} }
public void BeginRequestLifetime() {
RequestLifetime = ApplicationContainer.BeginLifetimeScope("httpRequest");
_requestContext.RouteData.DataTokens["IContainerProvider"] = this;
}
public void EndRequestLifetime() {
_requestContext.RouteData.DataTokens.Remove("IContainerProvider");
RequestLifetime.Dispose();
}
public IContainer ApplicationContainer { get; set; }
public ILifetimeScope RequestLifetime { get; set; }
} }
} }
} }