From 638002646c2e0e14282fc6fa6bebb89e35693f34 Mon Sep 17 00:00:00 2001 From: Andreas Kluth Date: Tue, 3 Dec 2013 23:08:33 +0100 Subject: [PATCH] SPRNET-1387: ASP.NET PageHandlerFactory cannot inject dependencies in the presence of the WebForms 4.0 routing infrastructure - Changed how the WebSupportModule detects when it should inject into a Page Signed-off-by: Andreas Kluth --- .../Context/Support/WebSupportModule.cs | 53 ++++++++++++++----- .../Objects/Factory/Support/WebObjectUtils.cs | 24 +-------- src/Spring/Spring.Web/Util/WebUtils.cs | 27 ++++++++++ .../Nms/Connections/CachedSessionTests.cs | 22 +++++++- .../Spring.Web.Tests/Util/WebUtilsTests.cs | 10 ++++ 5 files changed, 100 insertions(+), 36 deletions(-) diff --git a/src/Spring/Spring.Web/Context/Support/WebSupportModule.cs b/src/Spring/Spring.Web/Context/Support/WebSupportModule.cs index a5089467..b4db600f 100644 --- a/src/Spring/Spring.Web/Context/Support/WebSupportModule.cs +++ b/src/Spring/Spring.Web/Context/Support/WebSupportModule.cs @@ -18,31 +18,28 @@ #endregion -#region Imports - using System; using System.Globalization; using System.Reflection; using System.Security; -using System.Security.Permissions; using System.Web; using System.Web.Caching; +#if NET_4_0 +using System.Web.Routing; +#endif using System.Web.SessionState; using System.Web.UI; + using Common.Logging; using Spring.Core.IO; using Spring.Core.TypeConversion; using Spring.Core.TypeResolution; using Spring.Expressions; -using Spring.Objects.Factory.Config; -using Spring.Objects.Factory.Support; using Spring.Reflection.Dynamic; using Spring.Threading; using Spring.Util; using Spring.Web.Support; -#endregion - namespace Spring.Context.Support { /// @@ -181,19 +178,51 @@ namespace Spring.Context.Support #region IHttpHandler configuration - /// - /// Configures the current IHttpHandler as specified by . - /// + /// + /// Configures the current IHttpHandler as specified by . If the + /// is not executed for the current request and an instance of + /// is served revalidate if the instance should be configured. + /// private void OnConfigureHandler(object sender, EventArgs e) { + HttpApplication app = (HttpApplication)sender; HandlerConfigurationMetaData hCfg = (HandlerConfigurationMetaData)LogicalThreadContext.GetData(CURRENTHANDLER_OBJECTDEFINITION); if (hCfg != null) { - HttpApplication app = (HttpApplication)sender; // app.Context.Handler = // TODO: check, if this makes sense (EE) ConfigureHandlerNow(app.Context.Handler, hCfg.ApplicationContext, hCfg.ObjectDefinitionName, hCfg.IsContainerManaged); } +#if NET_4_0 + else + { + Page page = app.Context.Handler as Page; + if (!IsPageWithRouteHandler(page)) + { + return; + } + + // In case of Routing pages are not handled by the PageHandlerFactory therefore no HandlerConfigurationMetaData + // is set. + IConfigurableApplicationContext applicationContext = (IConfigurableApplicationContext)WebApplicationContext.Current; + string normalizedVirtualPath = WebUtils.GetNormalizedVirtualPath(page.AppRelativeVirtualPath); + + ControlInterceptor.EnsureControlIntercepted(applicationContext, page); + ConfigureHandlerNow(page, applicationContext, normalizedVirtualPath, true); + } +#endif + } + +#if NET_4_0 + /// + /// Determines whether the specified page is processed by a . + /// + /// the page. + /// whether the page has a page route assigned + private static bool IsPageWithRouteHandler(Page page) + { + return page != null && page.RouteData != null && page.RouteData.RouteHandler != null; } +#endif /// /// Configures the specified handler instance using the object definition . @@ -292,7 +321,7 @@ namespace Spring.Context.Support } else { - // this is an async session timout - log as fatal since this is the thread's exit point! + // this is an async session timeout - log as fatal since this is the thread's exit point! s_log.Fatal(msg, ex); } } diff --git a/src/Spring/Spring.Web/Objects/Factory/Support/WebObjectUtils.cs b/src/Spring/Spring.Web/Objects/Factory/Support/WebObjectUtils.cs index 9a3e2e26..ab17b12c 100644 --- a/src/Spring/Spring.Web/Objects/Factory/Support/WebObjectUtils.cs +++ b/src/Spring/Spring.Web/Objects/Factory/Support/WebObjectUtils.cs @@ -73,12 +73,6 @@ namespace Spring.Objects.Factory.Support s_log.Debug( "creating page instance '" + pageUrl + "'" ); } -// HttpContext ctx = HttpContext.Current; -// if (ctx == null) -// { -// throw new ObjectCreationException( -// "Unable to instantiate page. HttpContext is not defined." ); -// } IHttpHandler page; try { @@ -118,23 +112,7 @@ namespace Spring.Objects.Factory.Support /// internal static IHttpHandler CreateHandler( string pageUrl ) { - IHttpHandler page; -// HttpContext ctx = HttpContext.Current; -//#if NET_1_1 -// string physicalPath = ctx.Server.MapPath(pageUrl); -// s_log.Debug(string.Format("constructing page virtual path '{0}' from physical file '{1}'", pageUrl, physicalPath)); -// page = PageParser.GetCompiledPageInstance(pageUrl, physicalPath, ctx); -//#else -// string rootedVPath = WebUtils.CombineVirtualPaths( ctx.Request.CurrentExecutionFilePath, pageUrl ); -// if (s_log.IsDebugEnabled) -// { -// s_log.Debug( "page vpath is " + rootedVPath ); -// } -// -// page = BuildManager.CreateInstanceFromVirtualPath( rootedVPath, typeof( IHttpHandler ) ) as IHttpHandler; -//#endif - page = VirtualEnvironment.CreateInstanceFromVirtualPath(pageUrl, typeof (IHttpHandler)) as IHttpHandler; - return page; + return VirtualEnvironment.CreateInstanceFromVirtualPath(pageUrl, typeof(IHttpHandler)) as IHttpHandler; } /// diff --git a/src/Spring/Spring.Web/Util/WebUtils.cs b/src/Spring/Spring.Web/Util/WebUtils.cs index 80baa917..4c705862 100644 --- a/src/Spring/Spring.Web/Util/WebUtils.cs +++ b/src/Spring/Spring.Web/Util/WebUtils.cs @@ -226,6 +226,33 @@ namespace Spring.Util } /// + /// Gets a normalized application-relative virtual path of the given virtual path. + /// + /// + ///

+ /// Examples of what would be returned from this method given a virtual path would be: + ///

+ ///

+ /// + /// 'Login.aspx' => 'Login.aspx' + /// '~/Login.aspx' => '/Login.aspx' + /// '~/B2B/SignUp.aspx' => '/B2B/SignUp.aspx' + /// 'B2B/Foo/FooServices.aspx' => 'B2B/Foo/FooServices.aspx' + /// + ///

+ ///
+ /// the virtual path. + /// the normalized virtual path + public static string GetNormalizedVirtualPath(string virtualPath) + { + if(String.IsNullOrEmpty(virtualPath)) + { + return virtualPath; + } + return virtualPath.StartsWith("~/") ? virtualPath.Substring(1) : virtualPath; + } + + /// /// Gets the virtual path portion of the given absolute URL /// relative to the given base path. /// diff --git a/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Connections/CachedSessionTests.cs b/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Connections/CachedSessionTests.cs index ca239dc1..3b937130 100644 --- a/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Connections/CachedSessionTests.cs +++ b/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Connections/CachedSessionTests.cs @@ -1,4 +1,24 @@ -using Apache.NMS; +#region License + +/* + * Copyright © 2002-2013 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 Apache.NMS; using NUnit.Framework; using Spring.Collections; diff --git a/test/Spring/Spring.Web.Tests/Util/WebUtilsTests.cs b/test/Spring/Spring.Web.Tests/Util/WebUtilsTests.cs index 8bd01f0d..0e71a82d 100644 --- a/test/Spring/Spring.Web.Tests/Util/WebUtilsTests.cs +++ b/test/Spring/Spring.Web.Tests/Util/WebUtilsTests.cs @@ -271,5 +271,15 @@ namespace Spring.Util Assert.AreEqual("/mYpath", WebUtils.GetRelativePath("/Mydir", "/mYdir/mYpath")); Assert.AreEqual("/myotherdir/mypath", WebUtils.GetRelativePath("/mydir", "/myotherdir/mypath")); } + + [Test] + public void GetNormalizedVirtualPath() + { + Assert.AreEqual(null, WebUtils.GetNormalizedVirtualPath(null)); + Assert.AreEqual(String.Empty, WebUtils.GetNormalizedVirtualPath(String.Empty)); + Assert.AreEqual("~test.aspx", WebUtils.GetNormalizedVirtualPath("~test.aspx")); + Assert.AreEqual("/test.aspx", WebUtils.GetNormalizedVirtualPath("~/test.aspx")); + Assert.AreEqual("/Complex.Path/~/test.aspx", WebUtils.GetNormalizedVirtualPath("~/Complex.Path/~/test.aspx")); + } } } \ No newline at end of file