From a8d559a42696e7b12e58364ea4cccd7c7595e2bd Mon Sep 17 00:00:00 2001 From: sbohlen Date: Fri, 10 Dec 2010 19:05:03 +0000 Subject: [PATCH] SPRNET-1404 Added ActionInvoker --- .../Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj | 1 + .../Spring.Web.Mvc/SpringActionInvoker.cs | 84 +++++++++++++++++++ .../Spring.Web.Mvc/SpringControllerFactory.cs | 63 ++++++++++---- .../SpringControllerFactoryTests.cs | 66 ++++++++------- 4 files changed, 165 insertions(+), 49 deletions(-) create mode 100644 src/Spring/Spring.Web.Mvc/SpringActionInvoker.cs diff --git a/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj b/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj index 35d65ad9..f14e2a9e 100644 --- a/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj +++ b/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj @@ -56,6 +56,7 @@ + diff --git a/src/Spring/Spring.Web.Mvc/SpringActionInvoker.cs b/src/Spring/Spring.Web.Mvc/SpringActionInvoker.cs new file mode 100644 index 00000000..8536619f --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/SpringActionInvoker.cs @@ -0,0 +1,84 @@ +#region License + +/* + * Copyright © 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.Mvc; +using Spring.Context; +using Spring.Context.Support; + +namespace Spring.Web.Mvc +{ + /// + /// ActionInvoker implementation that enables the to satisfy dependencies on ActionFilter attributes. + /// + public class SpringActionInvoker : ControllerActionInvoker + { + private readonly IApplicationContext _context; + + /// + /// Initializes a new instance of the class. + /// + /// The IApplicationContext. + public SpringActionInvoker(IApplicationContext context) + { + _context = context; + } + + /// + /// Retrieves information about the action filters. + /// + /// The controller context. + /// The action descriptor. + /// Information about the action filters. + protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) + { + //let the base class do the actual work as usual + var filterInfo = base.GetFilters(controllerContext, actionDescriptor); + + //configure each collection of filters using the IApplicationContext + foreach (IActionFilter filter in filterInfo.ActionFilters.Where(f => f != null)) + { + _context.ConfigureObject(filter, filter.GetType().FullName); + } + + foreach (IAuthorizationFilter filter in filterInfo.AuthorizationFilters.Where(f => f != null)) + { + _context.ConfigureObject(filter, filter.GetType().FullName); + } + + foreach (IExceptionFilter filter in filterInfo.ExceptionFilters.Where(f => f != null)) + { + _context.ConfigureObject(filter, filter.GetType().FullName); + } + + foreach (IResultFilter filter in filterInfo.ResultFilters.Where(f => f != null)) + { + _context.ConfigureObject(filter, filter.GetType().FullName); + } + + return filterInfo; + } + + } + +} diff --git a/src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs b/src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs index 1d63fdbe..8e85fb8c 100644 --- a/src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs +++ b/src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs @@ -61,8 +61,14 @@ namespace Spring.Web.Mvc } } - - + /// + /// Gets or sets the name of the application context. + /// + /// + /// Defaults to using the root (default) Application Context. + /// + /// The name of the application context. + public static string ApplicationContextName { get; set; } /// /// Creates the specified controller by using the specified request context. @@ -74,22 +80,22 @@ namespace Spring.Web.Mvc /// The parameter is null or empty. public override IController CreateController(RequestContext requestContext, string controllerName) { + IController controller; + if (ApplicationContext.ContainsObjectDefinition(controllerName)) - return ApplicationContext.GetObject(controllerName) as IController; + { + controller = ApplicationContext.GetObject(controllerName) as IController; + } + else + { + controller = base.CreateController(requestContext, controllerName); + } - return base.CreateController(requestContext, controllerName); + AddActionInvokerTo(controller); + + return controller; } - - /// - /// Gets or sets the name of the application context. - /// - /// - /// Defaults to using the root (default) Application Context. - /// - /// The name of the application context. - public static string ApplicationContextName { get; set; } - /// /// Retrieves the controller instance for the specified request context and controller type. /// @@ -103,17 +109,40 @@ namespace Spring.Web.Mvc /// An instance of cannot be created. protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { + IController controller = null; + if (controllerType != null) { var controllers = ApplicationContext.GetObjectsOfType(controllerType); if (controllers.Count > 0) { - return (IController)controllers.Cast().First().Value; + controller = (IController)controllers.Cast().First().Value; } } + else + { + //pass to base class for remainder of handling if can't find it in the context + controller = base.GetControllerInstance(requestContext, controllerType); + } - //pass to base class for remainder of handling if can't find it in the context - return base.GetControllerInstance(requestContext, controllerType); + AddActionInvokerTo(controller); + + return controller; + } + + /// + /// Adds the action invoker to the controller instance. + /// + /// The controller. + protected virtual void AddActionInvokerTo(IController controller) + { + if (controller == null) + return; + + if (typeof(Controller).IsAssignableFrom(controller.GetType())) + { + ((Controller)controller).ActionInvoker = new SpringActionInvoker(ApplicationContext); + } } } diff --git a/test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs b/test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs index 43cbac6a..e42082db 100644 --- a/test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs +++ b/test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs @@ -1,19 +1,19 @@ #region License -/* - * Copyright © 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. +/* + * Copyright © 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #endregion @@ -41,9 +41,11 @@ namespace Spring.Web.Mvc.Tests public class SpringControllerFactoryTests { private MvcApplicationContext _context; - private MvcApplicationContext _mvcNamedContext; + private SpringControllerFactory _factory; + private MvcApplicationContext _mvcNamedContext; + [SetUp] public void _TestSetup() { @@ -65,16 +67,8 @@ namespace Spring.Web.Mvc.Tests typeof(NotInContainerController), typeof(NamedContextController), }); - } - [Test] - public void ProperlyResolvesCaseInsensitiveControllerNames() - { - IController pascalcaseController = _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "FirstContainerRegistered"); - IController lowercaseController = _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "firstcontainerregistered"); - - Assert.AreEqual(typeof(FirstContainerRegisteredController), pascalcaseController.GetType()); - Assert.AreEqual(typeof(FirstContainerRegisteredController), lowercaseController.GetType()); + SpringControllerFactory.ApplicationContextName = string.Empty; } [Test] @@ -84,6 +78,11 @@ namespace Spring.Web.Mvc.Tests Assert.AreEqual("Should_Be_Matched_By_Id", ((FirstContainerRegisteredController)controller).TestValue); } + [Test] + public void CanRetrieveControllersNotRegisteredWithContainer() + { + _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "NotInContainer"); + } [Test] public void CanRevertToTypeMatchIfIdMatchUnsuccessful() @@ -98,14 +97,6 @@ namespace Spring.Web.Mvc.Tests Assert.AreEqual("Should_Be_Matched_By_Type", ((FirstContainerRegisteredController)controller).TestValue); } - - [Test] - public void CanRetrieveControllersNotRegisteredWithContainer() - { - _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "NotInContainer"); - } - - [Test] public void CanUseNamedContextToResolveController() { @@ -114,5 +105,16 @@ namespace Spring.Web.Mvc.Tests Assert.NotNull(controller); } + + [Test] + public void ProperlyResolvesCaseInsensitiveControllerNames() + { + IController pascalcaseController = _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "FirstContainerRegistered"); + IController lowercaseController = _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "firstcontainerregistered"); + + Assert.AreEqual(typeof(FirstContainerRegisteredController), pascalcaseController.GetType()); + Assert.AreEqual(typeof(FirstContainerRegisteredController), lowercaseController.GetType()); + } + } }