C# 为什么可以';我是否与StateServer在两个web应用程序之间共享会话状态?我错过了什么?
我在使用会话状态服务器让两个相同的ASP.NET MVC应用程序共享同一会话时遇到问题。我尝试这样做的原因是,我们最终将在需要共享相同状态的3台web服务器上部署此应用程序。我们需要使用StateServer,因为我们试图将数据库用于非数据相关存储的使用降至最低 设置: 我已将相同的代码库部署到App1和App2 两者都有相同的Web.Config文件,如下所示:C# 为什么可以';我是否与StateServer在两个web应用程序之间共享会话状态?我错过了什么?,c#,asp.net,asp.net-mvc,session,stateserver,C#,Asp.net,Asp.net Mvc,Session,Stateserver,我在使用会话状态服务器让两个相同的ASP.NET MVC应用程序共享同一会话时遇到问题。我尝试这样做的原因是,我们最终将在需要共享相同状态的3台web服务器上部署此应用程序。我们需要使用StateServer,因为我们试图将数据库用于非数据相关存储的使用降至最低 设置: 我已将相同的代码库部署到App1和App2 两者都有相同的Web.Config文件,如下所示: <system.web> <sessionState mode="StateServer"
<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" />
鉴于此:
<p>
Mode: <%= ViewData["mode"].ToString() %>
</p>
<p>
Time: <%= ViewData["timestamp"].ToString() %>
</p>
<p>
real time: <%= ViewData["realtime"].ToString() %>
</p>
模式:
时间:
实时:
结果:
对于这两种部署,当页面第一次加载时,我可以看到模式是StateServer,时间戳设置为与realtime值相同的时间。。但是,如果这样做有效,则只有第一页的时间应该与realtime值相同。第二个页面加载应该从StateServer读取,因为时间戳值不再为null,并显示该时间值。但是,它会再次显示实时值
刷新页面时,时间戳保持不变,实时值始终在更新。这表示正在将时间戳保存到会话中,但两个部署的时间戳值始终不同(如果时间戳值应该相同),因此这表示未共享会话
有人能指出我是否做错了什么,或者我是否需要做些别的事情来让这一切顺利进行吗?谢谢默认情况下,会话不能在不同的应用程序之间共享。据我所见,您有两个不同的应用程序
App1
和App2
,它们运行在不同的虚拟目录中,甚至可能运行在不同的应用程序池中,因此不要期望在它们之间共享会话
像往常一样,你可能会发现一些有用的东西。正如您所看到的,它使用黑客(反射)来规避ASP.NET team designer不公开某些类和属性的决心,并使我们作为开发人员的生活变得困难。更新:这是我之前就同一主题回答的帖子 如前所述,会话数据的范围是应用程序。这是您在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
这两种情况下的效果是,您实际上将一个应用程序分为两个部分,两个部分都在相同的会话范围内,因此两个部分的代码可以共享相同的会话数据。您还必须确保应用程序在两个web服务器上的应用程序路径必须相同。这里有一篇老文章可能会有所帮助
我们目前也遇到了类似的问题,只是我们使用的是IIS 7.5,应用程序路径对我们来说是隐藏的(不再使用元数据库)。有人知道IIS 7.5的故障排除方法吗?实际上,您可以使用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
使用ASPState
去
ALTER过程dbo.TempGetAppID
@appName tAppName,
@appId int输出
作为
--开始改变
--如果指定了appname,请使用连接中指定的应用程序名称
--这使得我们只需确保站点具有
--连接字符串中的应用程序名称相同。
声明@connStrAppName nvarchar(50)
设置@connstrapName=APP_NAME()
--.NET SQLClient数据提供程序是.NET应用程序的默认应用程序名称
IF(@connstrapName'.NET SQLClient数据提供程序')
设置@appName=@connStrAppName
--换头
设置@appName=LOWER(@appName)
SET@appId=NULL
选择@appId=appId
来自[ASPState].dbo.ASPStateTempApplications
其中AppName=@AppName
如果@appId为空,则开始
开始训练
选择@appId=appId
来自[ASPState].dbo.ASPStateTempApplications和(TABLOCKX)
其中AppName=@AppName
如果@appId为空
开始
EXEC GetHashCode@appName,@appId输出
插入[ASPState].dbo.ASPStateTempApplications
价值观
(@appId,@appName)
如果@@ERROR=2627
开始
声明@dupApp-tAppName
选择@dupApp=RTRIM(AppName)
来自[ASPState].dbo.ASPStateTempApplications
其中AppId=@AppId
RAISERROR('SQL会话状态致命错误:应用程序“%s”和“%s”之间的哈希代码冲突。请重命名第一个应用程序以解决此问题。“”,
18,1,@appName,@dupApp)
结束
结束
犯罪
结束
返回0
去
然后将web.config修改为:-
<sessionState mode="SQLServer" sqlConnectionString="Data Source=.;Integrated Security=True;Application Name=TEST" cookieless="false" timeout="20"></sessionState>
<httpRuntime targetFramework="4.5"/>
您必须添加应用程序名称,并且对于要共享同一会话的所有应用程序,名称必须相同
谢谢。没错,它们是不同的应用程序。一个存在于D:\App1中,另一个存在于D:\App2中,并且位于IIS中DefaultWebSite下的不同虚拟目录中。但是,两者都在DefaultAppPool中。原因是我们最终将部署此应用程序
<sessionState mode="SQLServer" sqlConnectionString="Data Source=.;Integrated Security=True;Application Name=TEST" cookieless="false" timeout="20"></sessionState>
<httpRuntime targetFramework="4.5"/>