IIS7上的Spring.NET和MVC3 - 会话范围行为

时间:2011-05-19 14:39:37

标签: asp.net-mvc-3 scope spring.net

可能这是一个愚蠢的问题,我只是不明白Spring和IIS是如何工作的,但我们试一试。

我是ASP.NET的新手,据我所知,会话处理类似于Apache / PHP:

会话在浏览器的选项卡之间共享,但不在不同浏览器之间共享。即如果我在Firefox中打开我的页面并在购物车中放入一些东西,那么购物车仍然会在另一个标签中包含我的商品,但是在Internet Explorer中打开同一页面应该会显示一个空的购物车。

但是我无法使用Spring.NET重现这种行为。

我用购物车对象创建了一个hello-world,在会话范围中注明:

<objects xmlns="http://www.springframework.net">
  <object id="shoppingCart" type="DemoShop.Models.Cart.ShoppingCart, DemoShop" singleton="true" scope="session" />
</objects>

如果我在购物车中添加了某些内容,它会在任何标签页和浏览器中保留。所以这看起来好像这个对象是一个真正的单例,因此在IIS应用程序的运行时期间是持久的。

我知道,你要说的是:为什么我在spring配置中使用属性singleton="true"?好吧,如果我删除它或将其设置为false,那么该对象将不会在会话中保留,但会在每个请求上重新创建,从而丢失它的数据。

Spring.NET文档根本没有谈到MVC上下文中的singleton属性,我花了一些时间才弄明白,似乎需要使用MVC3。

我能够使用

成功创建应用程序范围对象
<object id="..." type="..., ..." singleton="true" scope="application" />

并使用

请求范围对象
<object id="..." type="..., ..." scope="request" />

<object id="..." type="..., ..." singleton="false" scope="request" />

但是保留singleton属性,无论我在scope属性中实际注意到哪个范围,都要将我的对象放在请求范围内。

我的猜测是,会话实际上并没有在Firefox和IE之间共享,但是cart对象只是在应用程序范围内,因为我使用的是错误的方式。

任何人都可以给我建议或提示我做错了什么,或者这是IIS7中的问题?

1 个答案:

答案 0 :(得分:2)

这是一个错误。

经过对spring.net源代码的一些过度调试后,我们发现:

  1. spring.web dll
  2. 提供对会话范围对象的支持
  3. spring.web.mvc dll不依赖于spring.web
  4. 这意味着,无法实例化可以解析会话范围对象的MvcApplicationContext
  5. 以下解决方案显示了一个自定义MvcApplicationContext,它使用spring.net在MVC3中完全启用了会话范围对象。

    标准应用程序上下文无法解析Web范围的原因是它使用类RootObjectDefinition而不知道scope属性(在config xml中)。而WebApplicationContext实例化RootWebObjectDefinition类型,它们知道范围。

    WebObjectsFactory会覆盖返回CreateRootObjectDefinition实例的方法RootWebObjectDefinition。这是我们想要从应用程序上下文返回的那个。这是通过覆盖方法CreateObjectsFactory完成的。

    接下来,我们必须覆盖方法CreateXmlObjectDefinitionReader。当spring从配置中读取元数据时,如果我们不接受特定的读者,它将不会解析其他属性,如scope。因此,我们将在应用程序上下文中使用WebObjectDefinitionReader

    对于会话范围对象的配置,您可以省略singleton属性或将其明确设置为true。否则值为false,会话范围将被禁用。

    实施例

    <objects xmlns="http://www.springframework.net">
        <object id="shoppingCart" type="ShoppingCart, ..." singleton="true" scope="session" />
    </objects>
    

    分步解决方案:

    1. 创建继承自MvcWebApplicationContext的{​​{1}}。您需要覆盖上面提到的两种方法并创建默认构造函数。
    2. 创建一个继承自MvcApplicationContext的{​​{1}}。这将触发我们的自定义应用程序上下文的使用。
    3. MvcWebContextHandler
    4. 中使用自定义上下文处理程序
    5. 对于IIS6支持或visual studio内置网络服务器:将MvcContextHandler添加到web.config部分。
    6. 对于IIS7支持:将WebSupportModule添加到system.web部分。
    7. 的web.config:

      WebSupportModule

      自定义应用程序上下文类:

      system.webserver

      自定义上下文处理程序类:

      <configSections>
          <sectionGroup name="spring">
              <section name="context" type="YourNamspace.MvcWebContextHandler, YourAssembly"/>    
              ....
          </sectionGroup>    
          ....
      </configSections>
      
      <!-- IIS6 -->
      <system.web>
          <httpModules>
              <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
          </httpModules>
      </system.web>
      
      <!-- IIS7 -->
      <system.webServer>
          <validation validateIntegratedModeConfiguration="false"/>
          <modules runAllManagedModulesForAllRequests="true" >
              <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
          </modules>
      </system.webServer>
      

      我们在Spring.NET的问题跟踪器中添加了这个bug: https://jira.springsource.org/browse/SPRNET-1450