我无法使用Session StateServer获得两个相同的ASP.NET MVC应用程序来共享同一个Session。我试图这样做的原因是我们最终将在3个需要共享相同状态的Web服务器上部署此应用程序。我们需要使用StateServer,因为我们正在尝试最小化数据库对非数据相关存储的使用。
设置:
我已将相同的代码库部署到http://localhost/ App1 和http://localhost/ App2
两者都有相同的Web.Config文件,其中包含以下内容:
<system.web>
<sessionState mode="StateServer"
cookieless="false"
timeout="20"
stateConnectionString="tcpip=127.0.0.1:42424" />
//stateConnectionString="tcpip=192.168.1.52:42424" /> // also doesn't work
<machineKey
validationKey="8B9F68D0CC730F6F046D0173021C34B1A0D9A01C21D8E4D4A7A1DFF38332DEE8CBBAFEA503C18776614EE9D4F7EEA7E5D2D5571630547D822485A27B1EF53AC1"
decryptionKey="60009563EFCFC594FD1BC46684943AA398EE70412A624B2EB488BBB071F15ECF"
validation="SHA1" decryption="AES" />
我使用了this tool to generate these machine keys
测试:
我将以下内容放入我的一个控制器中以测试它是否正常工作:
ViewData["mode"] = requestContext.HttpContext.Session.Mode.ToString();
string timestamp = DateTime.Now.ToString();
if (requestContext.HttpContext.Session["timestamp"] == null)
{
requestContext.HttpContext.Session["timestamp"] = timestamp;
}
ViewData["timestamp"] = requestContext.HttpContext.Session["timestamp"].ToString();
ViewData["realtime"] = timestamp;
在视图中显示:
<p>
Mode: <%= ViewData["mode"].ToString() %>
</p>
<p>
Time: <%= ViewData["timestamp"].ToString() %>
</p>
<p>
real time: <%= ViewData["realtime"].ToString() %>
</p>
结果:
对于这两个部署,当页面首次加载时,我可以看到模式是StateServer,时间戳设置为与实时值相同的时间。但是,如果这是有效的,只有第一页应该有与实时价值同时发生。第二页加载应从StateServer读取,因为该时间戳值不再为null,并显示该时间值。但相反,它再次显示实时价值。
刷新页面时,时间戳保持不变,实时值始终更新。这表示时间戳正在保存到会话中,但是当它们应该相同时,两个部署的时间戳值始终不同,因此这表示会话未被共享。
有人可以指出我做错了什么,或者我还需要做些什么才能让它发挥作用?感谢
答案 0 :(得分:10)
默认情况下,会话不能在不同的应用程序之间共享。从我所看到的,你有两个不同的应用程序App1
和App2
,它们运行在不同的虚拟目录中,甚至可能是独立的应用程序池,所以不要期望在它们之间共享会话。
与往常一样,您可能会发现workarounds有用。正如你所看到的那样,它正在使用hack(反射)来绕过ASP.NET团队设计师决心不暴露某些类和属性,并使我们的开发人员生活困难。
答案 1 :(得分:6)
实际上,您可以使用Sql server模式共享会话。
试试这个: -
我刚刚改变了程序,即
USE ASPState
GO
ALTER PROCEDURE dbo.TempGetAppID
@appName tAppName,
@appId int OUTPUT
AS
-- start change
-- Use the application name specified in the connection for the appname if specified
-- This allows us to share session between sites just by making sure they have the
-- the same application name in the connection string.
DECLARE @connStrAppName nvarchar(50)
SET @connStrAppName = APP_NAME()
-- .NET SQLClient Data Provider is the default application name for .NET apps
IF (@connStrAppName <> '.NET SQLClient Data Provider')
SET @appName = @connStrAppName
-- end change
SET @appName = LOWER(@appName)
SET @appId = NULL
SELECT @appId = AppId
FROM [ASPState].dbo.ASPStateTempApplications
WHERE AppName = @appName
IF @appId IS NULL BEGIN
BEGIN TRAN
SELECT @appId = AppId
FROM [ASPState].dbo.ASPStateTempApplications WITH (TABLOCKX)
WHERE AppName = @appName
IF @appId IS NULL
BEGIN
EXEC GetHashCode @appName, @appId OUTPUT
INSERT [ASPState].dbo.ASPStateTempApplications
VALUES
(@appId, @appName)
IF @@ERROR = 2627
BEGIN
DECLARE @dupApp tAppName
SELECT @dupApp = RTRIM(AppName)
FROM [ASPState].dbo.ASPStateTempApplications
WHERE AppId = @appId
RAISERROR('SQL session state fatal error: hash-code collision between applications ''%s'' and ''%s''. Please rename the 1st application to resolve the problem.',
18, 1, @appName, @dupApp)
END
END
COMMIT
END
RETURN 0
GO
然后将web.config修改为: -
<sessionState mode="SQLServer" sqlConnectionString="Data Source=.;Integrated Security=True;Application Name=TEST" cookieless="false" timeout="20"></sessionState>
<httpRuntime targetFramework="4.5"/>
您必须添加应用程序名称,并且必须与要共享同一会话的所有应用程序相同。
感谢。
答案 2 :(得分:3)
更新:这是我在同一主题上回答的上一篇文章 Sharing sessions across applications using the ASP.NET Session State Service
正如已经指出的那样,会话数据的范围是应用程序。这是您在IIS中创建的应用程序。因此,由于应用程序范围的限制,具有相同会话ID的两个应用程序将不会共享同一会话。
作为一种可能或可能不适合您的替代想法。 您可以创建一个根应用程序,并在两个子文件夹中包含D:\ App1和D:\ App2的代码。
d:\Root
web.config
\App1
default.aspx
...
\App2
default.aspx
...
然后在IIS中创建一个指向d:\ Root。
的应用程序您还可以在IIS中创建应用程序,然后在应用程序下创建两个虚拟目录,一个指向D:\ App1,另一个指向D:\ App2,然后它们也可以共享一个web.config
在应用程序级别。至关重要的是,两个虚拟目录只是虚拟目录而不是作为应用程序创建。
所以硬盘布局可能看起来像这样
D:\Root
web.config
D:\App1
default.aspx
...
D:\App2
default.aspx
...
创建指向D:\ Root的根应用程序,然后在应用程序下创建指向D:\ App1的两个虚拟目录App1和指向D:\ App2的App2。
两种情况下的效果都是您实际上有一个应用程序被拆分为两个部分,两个部分都在同一个Session范围内,因此两者的代码可以共享相同的会话数据。
答案 3 :(得分:2)
您还必须确保两个Web服务器上的应用程序的应用程序路径必须相同。这里有一篇旧文章可能会有所帮助
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q325056
我们目前遇到类似的问题,除了我们使用IIS 7.5并且我们隐藏了应用程序路径(不再使用元数据库)。有没有人知道使用IIS 7.5进行故障排除的方法?