2011-05-19 47 views
2

可能這是一個愚蠢的問題,我根本不明白Spring和IIS是如何工作的,但可以試試看。IIS7上的Spring.NET和MVC3 - 會話範圍行爲

我是相當新的ASP.NET和,據我瞭解,該會話處理類似的Apache/PHP:

一個會話瀏覽器的標籤頁之間共享,而不是不同的瀏覽器之間。即如果我在Firefox中打開我的頁面並將東西放入購物車中,購物車仍然會在另一個選項卡中包含我的物品,但在Internet Explorer中打開相同的頁面應該會向我顯示空的購物車。

但是我不能用Spring.NET重現這種行爲。

我做了一個hello世界與在會話範圍指出一個購物車對象:

<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屬性時,總是把我的對象放在請求範圍內,不管哪個sc我實際上注意到了scope屬性。

我的猜測是,會話實際上並不是在Firefox和IE之間共享,但購物車對象只是在應用程序範圍內,因爲我使用的是錯誤的方式。

任何人都可以給我意見或提示我做錯了什麼或者這是IIS7中的問題?

+0

有你設法解決這個問題?根據[webscopes上的文檔](http://www.springframework.net/doc-latest/reference/html/web-mvc.html#web-mvc-objectscope)在asp.net mvc中使用spring.net,它應該一定是''。是否可以使用' ''來禁用會話狀態? – Marijn 2011-05-24 12:28:09

+0

好吧,我已閱讀文檔,我完全同意你的看法。儘管如此,實例化對象總是處於請求範圍內,只要我省略「singleton」屬性即可。如果我不明確地將'singleton'設置爲'true',無論我的'scope'屬性如何表示,我甚至無法獲得應用程序作用域對象。這就是讓我如此好奇的原因。但是我還沒有解決它。我將創建一個簡單的MVC2 Hello World應用程序來檢查它是否像文檔所說的那樣工作。我也會檢查我的sessionState模式。當然我會在這裏發佈任何進展。謝謝! – Jan 2011-05-24 17:06:31

+0

我將Spring.NET應用於ASP.NET的默認MVC2應用程序,並重現了相同的行爲:'scope'屬性被忽略,'singleton'屬性創建應用程序範圍對象或請求範圍對象。所以這個問題一定是我。將進一步調查。 – Jan 2011-05-26 13:53:40

回答

2

這是一個錯誤。

經過對彈簧的過度調試。網源代碼,我們發現:

  1. 支持會話範圍內的對象由spring.web DLL
  2. 給出的spring.web.mvc DLL不依賴於spring.web
  3. 這意味着,這是不可能實例化一個MvcApplicationContext可解決會話作用域對象

以下解決方案顯示使用spring.net在MVC3中完全啓用會話作用域對象的自定義MvcApplicationContext

標準應用程序上下文無法解析web範圍的原因是它使用類RootObjectDefinition whis不知道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. 創建MvcWebApplicationContextMvcApplicationContext繼承。您將需要重寫上述兩個方法並創建默認構造函數。
  2. 創建從MvcContextHandler繼承的MvcWebContextHandler。這將觸發我們的自定義應用程序上下文將被使用。
  3. 在您的web.config中使用自定義上下文處理程序。
  4. 對於IIS6支持或Visual Studio內置網絡服務器:將WebSupportModule添加到system.web部分。
  5. 對於IIS7支持:將WebSupportModule添加到​​部分。

web。配置:

<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> 

自定義應用程序上下文類:

public class MvcWebApplicationContext: MvcApplicationContext { 

    public MvcWebApplicationContext(string name, bool caseSensitive, params string[] configurationLocations) 
    : this(new MvcApplicationContextArgs(name, null, configurationLocations, null, caseSensitive)) 
    { } 

    public MvcWebApplicationContext(string name, bool caseSensitive, IApplicationContext parentContext, params string[] configurationLocations) 
    : this(new MvcApplicationContextArgs(name, parentContext, configurationLocations, null, caseSensitive)) 
    { } 

    public MvcWebApplicationContext(MvcApplicationContextArgs args) 
    : base(args) 
    { } 

    public MvcWebApplicationContext(string name, bool caseSensitive, string[] configurationLocations, IResource[] configurationResources) 
    : this(new MvcApplicationContextArgs(name, null, configurationLocations, configurationResources, caseSensitive)) 
    { } 

    public MvcWebApplicationContext(params string[] configurationLocations) 
    : this(new MvcApplicationContextArgs(string.Empty, null, configurationLocations, null, false)) 
    { } 

    protected override XmlObjectDefinitionReader CreateXmlObjectDefinitionReader(DefaultListableObjectFactory objectFactory) 
    { 
     return new WebObjectDefinitionReader(GetContextPathWithTrailingSlash(), objectFactory, new XmlUrlResolver()); 
    } 

    protected override DefaultListableObjectFactory CreateObjectFactory() 
    { 
     return new WebObjectFactory(GetContextPathWithTrailingSlash(), IsCaseSensitive); 
    } 

    private string GetContextPathWithTrailingSlash() 
    { 
     string contextPath = this.Name; 
     if (contextPath == DefaultRootContextName) 
     { 
      contextPath = "/"; 
     } 
     else 
     { 
      contextPath = contextPath + "/"; 
     } 
     return contextPath; 
    } 
} 

自定義上下文句柄類:

public class MvcWebContextHandler : MvcContextHandler { 

    protected override Type DefaultApplicationContextType 
    { 
     get { return typeof(MvcWebApplicationContext); } 
    } 
} 

我們增加了這個bug到Spring.NET的問題跟蹤: https://jira.springsource.org/browse/SPRNET-1450

+1

這是Spring.net的issuetracker上的錯誤:https://jira.springsource.org/browse/SPRNET-1450 – Marijn 2011-06-09 09:13:24

+0

對不起,我忘記發佈了。我將jira鏈接添加到回覆帖子中。感謝您指出。 – Jan 2011-06-09 13:30:06

+0

好帖子;很高興看到您找到修復/解決方法。在Spring問題追蹤器中,我讀到這個錯誤得到了證實,並且在spring.net 1.3.2中修復了asp.net mvc 3.但是,對於1.3.1/asp.net mvc 2還沒有修復。 – Marijn 2011-06-09 19:03:15