From 124c18b59c22eb770ac8e9f122a3ac1542eb6f8f Mon Sep 17 00:00:00 2001 From: sbohlen Date: Tue, 26 Oct 2010 21:38:18 +0000 Subject: [PATCH] SPRNET-1343 Added initial support for ASP.NET MVC (v2) --- Spring.Net.2010.sln | 24 ++++ .../Spring.Data.NHibernate20.2010.csproj | 4 + .../HibernateTxScopeTransactionManager.cs | 12 ++ .../Context/Support/MvcApplicationContext.cs | 96 +++++++++++++ .../Support/MvcApplicationContextArgs.cs | 76 ++++++++++ .../Context/Support/MvcContextHandler.cs | 43 ++++++ .../Spring.Web.Mvc/Properties/AssemblyInfo.cs | 36 +++++ .../Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj | 68 +++++++++ .../Spring.Web.Mvc/Spring.Web.Mvc.build | 43 ++++++ .../Spring.Web.Mvc/SpringControllerFactory.cs | 93 ++++++++++++ .../Spring.Web.Mvc/SpringMvcApplication.cs | 88 ++++++++++++ ...HibernateTxScopeTransactionManagerTests.cs | 136 +++++++++++++++++- .../Data/NHibernate/SimpleTestDao.cs | 61 ++++++++ .../Data/NHibernate/txScopeBugTests.xml | 63 ++++++++ ...NHibernate21.Integration.Tests.2010.csproj | 2 + .../ControllerFactoryTestExtension.cs | 44 ++++++ .../FirstContainerRegisteredController.cs | 11 ++ .../Controllers/NamedContextController.cs | 11 ++ .../Controllers/NotInContainerController.cs | 11 ++ .../SecondContainerRegisteredController.cs | 11 ++ .../Properties/AssemblyInfo.cs | 36 +++++ .../Spring.Web.Mvc.Tests.2010.csproj | 81 +++++++++++ .../Spring.Web.Mvc.Tests.build | 71 +++++++++ .../SpringControllerFactoryTests.cs | 98 +++++++++++++ .../namedContextObjects.xml | 7 + test/Spring/Spring.Web.Mvc.Tests/objects.xml | 19 +++ .../objectsMatchByType.xml | 12 ++ 27 files changed, 1255 insertions(+), 2 deletions(-) create mode 100644 src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContext.cs create mode 100644 src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContextArgs.cs create mode 100644 src/Spring/Spring.Web.Mvc/Context/Support/MvcContextHandler.cs create mode 100644 src/Spring/Spring.Web.Mvc/Properties/AssemblyInfo.cs create mode 100644 src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj create mode 100644 src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.build create mode 100644 src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs create mode 100644 src/Spring/Spring.Web.Mvc/SpringMvcApplication.cs create mode 100644 test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/SimpleTestDao.cs create mode 100644 test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/txScopeBugTests.xml create mode 100644 test/Spring/Spring.Web.Mvc.Tests/ControllerFactoryTestExtension.cs create mode 100644 test/Spring/Spring.Web.Mvc.Tests/Controllers/FirstContainerRegisteredController.cs create mode 100644 test/Spring/Spring.Web.Mvc.Tests/Controllers/NamedContextController.cs create mode 100644 test/Spring/Spring.Web.Mvc.Tests/Controllers/NotInContainerController.cs create mode 100644 test/Spring/Spring.Web.Mvc.Tests/Controllers/SecondContainerRegisteredController.cs create mode 100644 test/Spring/Spring.Web.Mvc.Tests/Properties/AssemblyInfo.cs create mode 100644 test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.2010.csproj create mode 100644 test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.build create mode 100644 test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs create mode 100644 test/Spring/Spring.Web.Mvc.Tests/namedContextObjects.xml create mode 100644 test/Spring/Spring.Web.Mvc.Tests/objects.xml create mode 100644 test/Spring/Spring.Web.Mvc.Tests/objectsMatchByType.xml diff --git a/Spring.Net.2010.sln b/Spring.Net.2010.sln index 717a1217..b1bea551 100644 --- a/Spring.Net.2010.sln +++ b/Spring.Net.2010.sln @@ -70,6 +70,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Data.NHibernate30.Te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Data.NHibernate21.Integration.Tests.2010", "test\Spring\Spring.Data.NHibernate21.Integration.Tests\Spring.Data.NHibernate21.Integration.Tests.2010.csproj", "{4A07E150-ED90-407C-8CAD-4760444DDFD9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Web.Mvc.2010", "src\Spring\Spring.Web.Mvc\Spring.Web.Mvc.2010.csproj", "{5166CE3A-14BE-478A-88DA-729A39DE1E29}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Web.Mvc.Tests.2010", "test\Spring\Spring.Web.Mvc.Tests\Spring.Web.Mvc.Tests.2010.csproj", "{D4032434-D9A8-437B-95E8-9D4DE0AD9932}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|.NET = Debug|.NET @@ -410,6 +414,26 @@ Global {4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|Any CPU.Build.0 = Release|Any CPU {4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Debug|.NET.ActiveCfg = Debug|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Release|.NET.ActiveCfg = Release|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Release|Any CPU.Build.0 = Release|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5166CE3A-14BE-478A-88DA-729A39DE1E29}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Debug|.NET.ActiveCfg = Debug|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Release|.NET.ActiveCfg = Release|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Release|Any CPU.Build.0 = Release|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {D4032434-D9A8-437B-95E8-9D4DE0AD9932}.Release|Mixed Platforms.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Spring/Spring.Data.NHibernate20/Spring.Data.NHibernate20.2010.csproj b/src/Spring/Spring.Data.NHibernate20/Spring.Data.NHibernate20.2010.csproj index 138bf3ac..ea9ab0f5 100644 --- a/src/Spring/Spring.Data.NHibernate20/Spring.Data.NHibernate20.2010.csproj +++ b/src/Spring/Spring.Data.NHibernate20/Spring.Data.NHibernate20.2010.csproj @@ -50,6 +50,7 @@ + @@ -87,6 +88,9 @@ Data\NHibernate\SpringSessionSynchronization.cs + + Data\NHibernate\HibernateTxScopeTransactionManager.cs + Data\NHibernate\HibernateAdoException.cs diff --git a/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs b/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs index 56da95b9..50844402 100644 --- a/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs +++ b/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs @@ -676,6 +676,10 @@ namespace Spring.Data.NHibernate } + /// + /// Does the tx scope commit. + /// + /// The status. protected void DoTxScopeCommit(DefaultTransactionStatus status) { TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject = @@ -742,6 +746,10 @@ namespace Spring.Data.NHibernate } } + /// + /// Does the tx scope rollback. + /// + /// The status. protected void DoTxScopeRollback(DefaultTransactionStatus status) { TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject = @@ -779,6 +787,10 @@ namespace Spring.Data.NHibernate DoTxScopeSetRollbackOnly(status); } + /// + /// Does the tx scope set rollback only. + /// + /// The status. protected void DoTxScopeSetRollbackOnly(DefaultTransactionStatus status) { if (status.Debug) diff --git a/src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContext.cs b/src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContext.cs new file mode 100644 index 00000000..aae11532 --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContext.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Spring.Context.Support; +using Spring.Core.IO; + +namespace Spring.Context.Support +{ + /// + /// Application Context for ASP.NET MVC Applications + /// + public class MvcApplicationContext : AbstractXmlApplicationContext + { + private readonly string[] _configurationLocations; + + private readonly IResource[] _configurationResources; + + /// + /// Create a new MvcApplicationContext, loading the definitions + /// from the given XML resource. + /// + /// The application context name. + /// Flag specifying whether to make this context case sensitive or not. + /// Names of configuration resources. + public MvcApplicationContext(string name, bool caseSensitive, params string[] configurationLocations) + : this(new MvcApplicationContextArgs(name, null, configurationLocations, null, caseSensitive)) + { + } + + /// + /// Create a new MvcApplicationContext with the given parent, + /// loading the definitions from the given XML resources. + /// + /// The application context name. + /// Flag specifying whether to make this context case sensitive or not. + /// The parent context. + /// Names of configuration resources. + public MvcApplicationContext(string name, bool caseSensitive, IApplicationContext parentContext, + params string[] configurationLocations) + : this(new MvcApplicationContextArgs(name, parentContext, configurationLocations, null, caseSensitive)) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The args. + public MvcApplicationContext(MvcApplicationContextArgs args) + : base(args.Name, args.CaseSensitive, args.ParentContext) + { + _configurationLocations = args.ConfigurationLocations; + _configurationResources = args.ConfigurationResources; + + Refresh(); + + if (log.IsDebugEnabled) + { + log.Debug("created instance " + this.ToString()); + } + } + + /// + /// Create a new MvcApplicationContext, loading the definitions + /// from the given XML resource. + /// + /// The application context name. + /// Flag specifying whether to make this context case sensitive or not. + /// Names of configuration resources. + /// Configuration resources. + public MvcApplicationContext(string name, bool caseSensitive, string[] configurationLocations, IResource[] configurationResources) + : this(new MvcApplicationContextArgs(name, null, configurationLocations, configurationResources, caseSensitive)) + { + } + + /// + /// Create a new MvcApplicationContext, loading the definitions + /// from the given XML resource. + /// + /// Names of configuration resources. + public MvcApplicationContext(params string[] configurationLocations) + : this(new MvcApplicationContextArgs(string.Empty, null, configurationLocations, null, false)) + { + } + + protected override string[] ConfigurationLocations + { + get { return _configurationLocations; } + } + + protected override IResource[] ConfigurationResources + { + get { return _configurationResources; } + } + + } +} diff --git a/src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContextArgs.cs b/src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContextArgs.cs new file mode 100644 index 00000000..be79afcc --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/Context/Support/MvcApplicationContextArgs.cs @@ -0,0 +1,76 @@ +#region License + +/* + * Copyright © 2002-2005 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 Spring.Core.IO; + +namespace Spring.Context.Support +{ + /// + /// Encapsulates arguments to the class. + /// + public class MvcApplicationContextArgs : AbstractXmlApplicationContextArgs + { + + private const bool DEFAULT_CASESENSITIVE = false; + private const bool DEFAULT_REFRESH = false; + + /// + /// Initializes a new instance of the MvcApplicationContextArgs class. + /// + public MvcApplicationContextArgs() + { + CaseSensitive = DEFAULT_CASESENSITIVE; + } + + /// + /// Initializes a new instance of the MvcApplicationContextArgs class. + /// + /// The name. + /// The parent context. + /// The configuration locations. + /// The configuration resources. + public MvcApplicationContextArgs(string name, IApplicationContext parentContext, string[] configurationLocations, IResource[] configurationResources) + : this(name, parentContext, configurationLocations, configurationResources, DEFAULT_CASESENSITIVE) + { } + + + /// + /// Initializes a new instance of the MvcApplicationContextArgs class. + /// + /// The name. + /// The parent context. + /// The configuration locations. + /// The configuration resources. + /// if set to true [case sensitive]. + public MvcApplicationContextArgs(string name, IApplicationContext parentContext, string[] configurationLocations, IResource[] configurationResources, bool caseSensitive) + { + Name = name; + ParentContext = parentContext; + ConfigurationLocations = configurationLocations; + ConfigurationResources = configurationResources; + CaseSensitive = caseSensitive; + Refresh = DEFAULT_REFRESH; + } + + + } +} diff --git a/src/Spring/Spring.Web.Mvc/Context/Support/MvcContextHandler.cs b/src/Spring/Spring.Web.Mvc/Context/Support/MvcContextHandler.cs new file mode 100644 index 00000000..9cc2c353 --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/Context/Support/MvcContextHandler.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Spring.Context.Support; + +namespace Spring.Context.Support +{ + /// + /// Context Handler for ASP.NET MVC Applications + /// + public class MvcContextHandler : ContextHandler + { + /// + /// The of + /// created if no type attribute is specified on a context element. + /// + /// + /// + protected override Type DefaultApplicationContextType + { + get { return typeof(MvcApplicationContext); } + } + + + /// + /// Get the context's case-sensitivity to use if none is specified + /// + /// + /// + ///

+ /// Derived handlers may override this property to change their default case-sensitivity. + ///

+ ///

+ /// Defaults to 'true'. + ///

+ ///
+ protected override bool DefaultCaseSensitivity + { + get { return false; } + } + } +} diff --git a/src/Spring/Spring.Web.Mvc/Properties/AssemblyInfo.cs b/src/Spring/Spring.Web.Mvc/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..89ac954d --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Spring.Web.Mvc")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Spring.Web.Mvc")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4e7f33fc-585f-44cb-b8b9-500223e9b760")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj b/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj new file mode 100644 index 00000000..9765146a --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.2010.csproj @@ -0,0 +1,68 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5166CE3A-14BE-478A-88DA-729A39DE1E29} + Library + Properties + Spring.Web.Mvc + Spring.Web.Mvc + v3.5 + 512 + + + true + full + false + ..\..\..\bin\net\3.5\debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + {710961A3-0DF4-49E4-A26E-F5B9C044AC84} + Spring.Core.2010 + + + + + \ No newline at end of file diff --git a/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.build b/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.build new file mode 100644 index 00000000..0b64ce05 --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/Spring.Web.Mvc.build @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs b/src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs new file mode 100644 index 00000000..77d8f017 --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/SpringControllerFactory.cs @@ -0,0 +1,93 @@ +using System; +using System.Web.Mvc; +using System.Web.Routing; +using Spring.Objects.Factory; +using Spring.Core; +using Spring.Context; +using Spring.Context.Support; +using System.Linq; +using System.Collections; + +namespace Spring.Web.Mvc +{ + /// + /// Controller Factory for ASP.NET MVC + /// + public class SpringControllerFactory : DefaultControllerFactory + { + private static IApplicationContext _context; + + public static IApplicationContext ApplicationContext + { + get + { + if (_context == null || _context.Name != ApplicationContextName) + { + if (string.IsNullOrEmpty(ApplicationContextName)) + { + _context = ContextRegistry.GetContext(); + } + else + { + _context = ContextRegistry.GetContext(ApplicationContextName); + } + } + + return _context; + } + } + + /// + /// Creates the specified controller by using the specified request context. + /// + /// The context of the HTTP request, which includes the HTTP context and route data. + /// The name of the controller. + /// A reference to the controller. + /// The parameter is null. + /// The parameter is null or empty. + public override IController CreateController(RequestContext requestContext, string controllerName) + { + if (ApplicationContext.ContainsObjectDefinition(controllerName)) + return ApplicationContext.GetObject(controllerName) as IController; + + return base.CreateController(requestContext, controllerName); + } + + + /// + /// 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. + /// + /// The context of the HTTP request, which includes the HTTP context and route data. + /// The type of the controller. + /// The controller instance. + /// + /// is null. + /// + /// cannot be assigned. + /// An instance of cannot be created. + protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) + { + if (controllerType != null) + { + var controllers = ApplicationContext.GetObjectsOfType(controllerType); + if (controllers.Count > 0) + { + return (IController)controllers.Cast().First().Value; + } + } + + //pass to base class for remainder of handling if can't find it in the context + return base.GetControllerInstance(requestContext, controllerType); + } + + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Web.Mvc/SpringMvcApplication.cs b/src/Spring/Spring.Web.Mvc/SpringMvcApplication.cs new file mode 100644 index 00000000..2eee8da2 --- /dev/null +++ b/src/Spring/Spring.Web.Mvc/SpringMvcApplication.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.Mvc; +using Spring.Objects.Factory; +using Spring.Core.IO; +using Spring.Objects.Factory.Xml; +using System.Web.Routing; +using Spring.Context.Support; + +namespace Spring.Web.Mvc +{ + public abstract class SpringMvcApplication : HttpApplication + { + protected virtual void Application_Start(object sender, EventArgs e) + { + RegisterAreas(); + RegisterRoutes(RouteTable.Routes); + } + + /// + /// Configures the instance. + /// + /// + /// You must override this method in a derived class to control the manner in which the + /// is configured. + /// + protected virtual void ConfigureApplicationContext() + { + + } + + + public override void Init() + { + base.Init(); + + //the Spring HTTP Module won't have built the context for us until now so we have to delay until the init + ConfigureApplicationContext(); + RegisterSpringControllerFactory(); + } + + /// + /// Registers the areas. + /// + /// + /// Override this method in a derived class to modify the registered areas as neeeded. + /// + protected virtual void RegisterAreas() + { + AreaRegistration.RegisterAllAreas(); + } + + /// + /// Registers the routes. + /// + /// + /// Override this method in a derived class to modify the registered routes as neeeded. + /// + protected virtual void RegisterRoutes(RouteCollection routes) + { + // This IgnoreRoute call is provided to avoid the trouble of CASSINI passing all req's thru + // ASP.NET (and thus the controller pipeline) during debugging + // see http://stackoverflow.com/questions/487230/serving-favicon-ico-in-asp-net-mvc and elsewhere for more info + routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); + + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + "Default", // Route name + "{controller}/{action}/{id}", // URL with parameters + new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults + ); + + } + + /// + /// Registers the controller factory with the Mvc Framework. + /// + protected virtual void RegisterSpringControllerFactory() + { + ControllerBuilder.Current.SetControllerFactory(typeof(SpringControllerFactory)); + } + + } +} diff --git a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs index 31d2ef78..d2030320 100644 --- a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs +++ b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs @@ -29,12 +29,14 @@ using NUnit.Framework; using Spring.Context; using Spring.Context.Support; using Spring.Data.Common; -using Spring.Data.Support; using Spring.Transaction; -using Spring.Transaction.Support; using Spring.Transaction.Interceptor; using System.Transactions; using System.Collections.Generic; +using Spring.Core.IO; +using NHibernate.Cfg; +using System.Diagnostics; +using System.Threading; #endregion @@ -202,5 +204,135 @@ namespace Spring.Data.NHibernate cmd.ExecuteNonQuery(); } + [Test] + public void Test2() + { + for (int i = 0; i < 200; i++) + { + //DaoOperationsViaProxyFactoryWithTxAttributes(); + try + { + zzzExecuteDaoOperations(); + } + catch (Exception) + { + + } + } + } + + private void zzzExecuteDaoOperations() + { + ITestObjectDao dao = (ITestObjectDao)ctx["SimpleTestDao"]; + + TestObject toGeorge = new TestObject(); + toGeorge.Name = "George"; + toGeorge.Age = 33; + dao.Create(toGeorge); + } + + + //private void MethodForThread() + //{ + // + // MethodForThread((0)); + //} + + private void MethodForThread(object taskCounter) + { + int counter = (int)taskCounter; + + for (int i = 0; i < 200; i++) + { + try + { + Debug.WriteLine(String.Format("Task: {0} | Loop Count: {1}", counter, i)); + zzzExecuteDaoOperations(); + } + catch (Exception) + { + + } + } + + Debug.WriteLine(String.Format("\n---------\nCompleting Task Number {0}\n---------\n", taskCounter)); + } + + + [Test] + public void Test() + { + BasicConfigurator.Configure(); + string assemblyName = GetType().Assembly.GetName().Name; + ctx = new XmlApplicationContext("assembly://" + assemblyName + "/Spring.Data.NHibernate/txScopeBugTests.xml"); + + dbProvider = ctx["DbProvider"] as IDbProvider; + transactionManager = ctx["TransactionManager"] as IPlatformTransactionManager; + CleanupDatabase(dbProvider.CreateConnection()); + + List threads = new List(); + + for (int i = 0; i < 200; i++) + { + int taskCounter = i; + Debug.WriteLine(String.Format("\n---------\nSpawning Task Number {0}\n---------\n", taskCounter)); + + Thread t = new Thread(MethodForThread); + threads.Add(t); + t.Start(taskCounter); + + } + + foreach (Thread thread in threads) + { + thread.Join(); + } + } + + public void DoNothing() + { + ConfigurableResourceLoader loader = new ConfigurableResourceLoader(); + Configuration c = new Configuration(); + String resourceName = + "assembly://Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate/TestObject.hbm.xml"; + c.AddInputStream(loader.GetResource(resourceName).InputStream); + ISessionFactory sf = c.BuildSessionFactory(); + } + + + + [Test] + public void LeaksConnectionSampleCodeFromBlogPost() + { + + int counter = 200; + + for (int i = 0; i < counter; i++) + { + + using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required)) + { + using (ISession session = ((ISessionFactory)ctx["SessionFactory"]).OpenSession()) + { + /* + IQuery q = session.CreateQuery("from Spring.Data.NHibernate.TestObject"); + q.List(); + */ + + using (ITransaction transaction = session.BeginTransaction()) + { + IQuery q = session.CreateQuery("from Spring.Data.NHibernate.TestObject"); + q.List(); + //transaction.Rollback(); + } + + } + } + + } + + } + } + } diff --git a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/SimpleTestDao.cs b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/SimpleTestDao.cs new file mode 100644 index 00000000..5991df14 --- /dev/null +++ b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/SimpleTestDao.cs @@ -0,0 +1,61 @@ +using System; +using NHibernate; +using Spring.Transaction.Interceptor; +using System.Threading; + +namespace Spring.Data.NHibernate +{ + [Transaction] + public class SimpleTestDao : ITestObjectDao + { + + private int _secondsToSleepBeforeException; + public int SecondsToSleepBeforeException + { + get { return _secondsToSleepBeforeException; } + set + { + _secondsToSleepBeforeException = value * 1000; + } + } + + + public ISessionFactory SessionFactory + { + get { return sessionFactory; } + set { sessionFactory = value; } + } + + private ISessionFactory sessionFactory; + + [Transaction] + public void Create(TestObject to) + { + sessionFactory.GetCurrentSession().FlushMode = FlushMode.Always; + sessionFactory.GetCurrentSession().Save(to); + Thread.Sleep(_secondsToSleepBeforeException); + + throw new Exception(); + } + + public void Update(TestObject to) + { + throw new NotImplementedException(); + } + + public void Delete(TestObject to) + { + throw new NotImplementedException(); + } + + public TestObject FindByName(string name) + { + throw new NotImplementedException(); + } + + public void CreateUpdateRollback(TestObject to) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/txScopeBugTests.xml b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/txScopeBugTests.xml new file mode 100644 index 00000000..bbcdbdbd --- /dev/null +++ b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/txScopeBugTests.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + assembly://Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate/TestObject.hbm.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj index 5eb83fa7..6a4c2ba9 100644 --- a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj +++ b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj @@ -147,6 +147,7 @@ + @@ -205,6 +206,7 @@ + Always diff --git a/test/Spring/Spring.Web.Mvc.Tests/ControllerFactoryTestExtension.cs b/test/Spring/Spring.Web.Mvc.Tests/ControllerFactoryTestExtension.cs new file mode 100644 index 00000000..e3e19105 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/ControllerFactoryTestExtension.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Web; +using System.Web.Routing; +using Spring.Core.IO; +using Spring.Objects.Factory; +using Spring.Objects.Factory.Xml; +using System.Web.Mvc; +using Spring.Web.Mvc.Tests.Controllers; +using Spring.Context.Support; +using System.Reflection; + +namespace Spring.Web.Mvc.Tests +{ + public static class ControllerFactoryTestExtension + { + private static readonly PropertyInfo _typeCacheProperty; + private static readonly FieldInfo _cacheField; + + static ControllerFactoryTestExtension() + { + _typeCacheProperty = typeof(DefaultControllerFactory).GetProperty("ControllerTypeCache", BindingFlags.Instance | BindingFlags.NonPublic); + _cacheField = _typeCacheProperty.PropertyType.GetField("_cache", BindingFlags.NonPublic | BindingFlags.Instance); + } + + /// + /// Replaces the cache field of a the DefaultControllerFactory's ControllerTypeCache. + /// This ensures that only the specified controller types will be searched when instantiating a controller. + /// As the ControllerTypeCache is internal, this uses some reflection hackery. + /// + public static void InitializeWithControllerTypes(this IControllerFactory factory, params Type[] controllerTypes) + { + var cache = controllerTypes + .GroupBy(t => t.Name.Substring(0, t.Name.Length - "Controller".Length), StringComparer.OrdinalIgnoreCase) + .ToDictionary(g => g.Key, g => g.ToLookup(t => t.Namespace ?? string.Empty, StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase); + + var buildManager = _typeCacheProperty.GetValue(factory, null); + _cacheField.SetValue(buildManager, cache); + } + } +} diff --git a/test/Spring/Spring.Web.Mvc.Tests/Controllers/FirstContainerRegisteredController.cs b/test/Spring/Spring.Web.Mvc.Tests/Controllers/FirstContainerRegisteredController.cs new file mode 100644 index 00000000..4be91a98 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/Controllers/FirstContainerRegisteredController.cs @@ -0,0 +1,11 @@ +using System; +using System.Web; +using System.Web.Mvc; + +namespace Spring.Web.Mvc.Tests.Controllers +{ + public class FirstContainerRegisteredController : Controller + { + public string TestValue { get; set; } + } +} diff --git a/test/Spring/Spring.Web.Mvc.Tests/Controllers/NamedContextController.cs b/test/Spring/Spring.Web.Mvc.Tests/Controllers/NamedContextController.cs new file mode 100644 index 00000000..6d3cdaef --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/Controllers/NamedContextController.cs @@ -0,0 +1,11 @@ +using System; +using System.Web; +using System.Web.Mvc; + +namespace Spring.Web.Mvc.Tests.Controllers +{ + public class NamedContextController : Controller + { + + } +} diff --git a/test/Spring/Spring.Web.Mvc.Tests/Controllers/NotInContainerController.cs b/test/Spring/Spring.Web.Mvc.Tests/Controllers/NotInContainerController.cs new file mode 100644 index 00000000..1fae7373 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/Controllers/NotInContainerController.cs @@ -0,0 +1,11 @@ +using System; +using System.Web; +using System.Web.Mvc; + +namespace Spring.Web.Mvc.Tests.Controllers +{ + public class NotInContainerController : Controller + { + + } +} diff --git a/test/Spring/Spring.Web.Mvc.Tests/Controllers/SecondContainerRegisteredController.cs b/test/Spring/Spring.Web.Mvc.Tests/Controllers/SecondContainerRegisteredController.cs new file mode 100644 index 00000000..ac154028 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/Controllers/SecondContainerRegisteredController.cs @@ -0,0 +1,11 @@ +using System; +using System.Web; +using System.Web.Mvc; + +namespace Spring.Web.Mvc.Tests.Controllers +{ + public class SecondContainerRegisteredController : Controller + { + + } +} diff --git a/test/Spring/Spring.Web.Mvc.Tests/Properties/AssemblyInfo.cs b/test/Spring/Spring.Web.Mvc.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..f03211a9 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Spring.Web.Mvc.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Spring.Web.Mvc.Tests")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3f96ac7b-cd25-4d07-8b1c-ee2eb77cf5eb")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.2010.csproj b/test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.2010.csproj new file mode 100644 index 00000000..c5d9d7e0 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.2010.csproj @@ -0,0 +1,81 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {D4032434-D9A8-437B-95E8-9D4DE0AD9932} + Library + Properties + Spring.Web.Mvc.Tests + Spring.Web.Mvc.Tests + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + {710961A3-0DF4-49E4-A26E-F5B9C044AC84} + Spring.Core.2010 + + + {5166CE3A-14BE-478A-88DA-729A39DE1E29} + Spring.Web.Mvc.2010 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.build b/test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.build new file mode 100644 index 00000000..8b864b0a --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests.build @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs b/test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs new file mode 100644 index 00000000..ed13307a --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/SpringControllerFactoryTests.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Web; +using System.Web.Routing; +using Spring.Core.IO; +using Spring.Objects.Factory; +using Spring.Objects.Factory.Xml; +using System.Web.Mvc; +using Spring.Web.Mvc.Tests.Controllers; +using Spring.Context.Support; +using System.Reflection; + +namespace Spring.Web.Mvc.Tests +{ + internal class MockContext : HttpContextBase { } + + [TestFixture] + public class SpringControllerFactoryTests + { + private MvcApplicationContext _context; + private MvcApplicationContext _mvcNamedContext; + private SpringControllerFactory _factory; + + [SetUp] + public void _TestSetup() + { + ContextRegistry.Clear(); + _context = new MvcApplicationContext("assembly://Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests/objects.xml"); + _mvcNamedContext = new MvcApplicationContext("named", false, "assembly://Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests/namedContextObjects.xml"); + + ContextRegistry.RegisterContext(_context); + ContextRegistry.RegisterContext(_mvcNamedContext); + + _factory = new SpringControllerFactory(); + + //due to ridiculous internal methods in DefaultControllerFactory, have to set the ControllerTypeCache using this extension method + // see http://stackoverflow.com/questions/727181/asp-net-mvc-system-web-compilation-compilationlock for more info + _factory.InitializeWithControllerTypes(new[] + { + typeof(FirstContainerRegisteredController), + typeof(SecondContainerRegisteredController), + 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()); + } + + [Test] + public void CanPreferIdMatchOverTypeMatch() + { + IController controller = _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "FirstContainerRegistered"); + Assert.AreEqual("Should_Be_Matched_By_Id", ((FirstContainerRegisteredController)controller).TestValue); + } + + + [Test] + public void CanRevertToTypeMatchIfIdMatchUnsuccessful() + { + MvcApplicationContext context = new MvcApplicationContext("assembly://Spring.Web.Mvc.Tests/Spring.Web.Mvc.Tests/objectsMatchByType.xml"); + + ContextRegistry.Clear(); + ContextRegistry.RegisterContext(context); + + IController controller = _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "FirstContainerRegistered"); + + 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() + { + SpringControllerFactory.ApplicationContextName = "named"; + IController controller = _factory.CreateController(new RequestContext(new MockContext(), new RouteData()), "NamedContext"); + + Assert.NotNull(controller); + } + } +} diff --git a/test/Spring/Spring.Web.Mvc.Tests/namedContextObjects.xml b/test/Spring/Spring.Web.Mvc.Tests/namedContextObjects.xml new file mode 100644 index 00000000..dcce9a85 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/namedContextObjects.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/test/Spring/Spring.Web.Mvc.Tests/objects.xml b/test/Spring/Spring.Web.Mvc.Tests/objects.xml new file mode 100644 index 00000000..90035d5d --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/objects.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + diff --git a/test/Spring/Spring.Web.Mvc.Tests/objectsMatchByType.xml b/test/Spring/Spring.Web.Mvc.Tests/objectsMatchByType.xml new file mode 100644 index 00000000..5f377f01 --- /dev/null +++ b/test/Spring/Spring.Web.Mvc.Tests/objectsMatchByType.xml @@ -0,0 +1,12 @@ + + + + + + + + + +