为什么我不能使用 StateServer 在 2 个 Web 应用程序之间共享会话状态?我缺少什么?
我无法让 2 个相同的 ASP.NET MVC 应用程序使用会话状态服务器共享同一个会话。我尝试这样做的原因是我们最终将在 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" />
我使用此工具生成这些机器密钥
测试:< /strong>
我将以下内容放入我的一个控制器中以测试它是否正常工作:
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 读取,因为该时间戳值不再为空,并显示该时间值。但相反,它再次显示实时值。
当我刷新页面时,时间戳保持不变,实时值始终更新。这表明时间戳正在保存到会话中,但是两个部署的时间戳值在本应相同的情况下始终不同,因此这表明会话没有被共享。
有人可以指出我是否做错了什么,或者我是否需要做其他事情才能使其正常工作?谢谢
I'm having trouble getting 2 identical ASP.NET MVC applications to share the same Session using a Session StateServer. The reason I'm trying to do this is we will eventually be deploying this app across 3 web servers that need to share the same state. We need to use StateServer because we are trying to minimise use of the db for non data-related storage.
The Setup:
I've deployed the same code base to http://localhost/App1 and http://localhost/App2
both have identical Web.Config files with the following:
<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" />
I used this tool to generate these machine keys
The Test:
I put the following into one of my Controllers to test if it was working:
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;
with this in the view:
<p>
Mode: <%= ViewData["mode"].ToString() %>
</p>
<p>
Time: <%= ViewData["timestamp"].ToString() %>
</p>
<p>
real time: <%= ViewData["realtime"].ToString() %>
</p>
The Result:
For both deployments, when the page first loads I can see that the mode is StateServer and the timestamp is getting set to the same time as the realtime value.. However, if this was working, only the first page should have the same time as the realtime value. The second page load should read from the StateServer because that timestamp value is no longer null, and display that time value. But instead, it's displaying the realtime value again.
When I refresh the page, I the timestamp stays the same and the realtime value is always updating. This indicates that the timestamp is being saved to the Session, but the time stamp value is always different for both deployments when it should be the same, so this indicates that the Session is not being shared.
Can somebody point out if I'm doing something wrong or if there's something else I need to do to get this to work? Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(4)
实际上,您可以使用 Sql 服务器模式共享会话。
试试这个:-
我刚刚更改了程序 ie
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"/>
您必须添加应用程序名称,并且对于您想要共享同一会话的所有应用程序来说,该名称必须相同。
谢谢。
更新:这是我之前就同一主题回答过的帖子
使用 ASP.NET 会话在应用程序之间共享会话状态服务
正如已经指出的,会话数据的范围仅限于应用程序。这就是您在 IIS 中创建的应用程序。因此,由于应用程序范围的原因,具有相同会话 ID 的两个应用程序将不会共享同一会话。
作为一种替代想法,对您来说可能可行,也可能不可行。
您可以创建一个根应用程序,并将 D:\App1 和 D:\App2 的代码放在两个子文件夹中。
d:\Root
web.config
\App1
default.aspx
...
\App2
default.aspx
...
然后在 IIS 中创建一个指向 d:\Root 的应用程序。
你也可以在IIS中创建一个Application,然后在该Application下创建两个虚拟目录,一个指向D:\App1,另一个指向D:\App2,那么它们也可以共享一个web.config 在应用程序级别。至关重要的是,这两个虚拟目录只是虚拟的,而不是作为应用程序创建的。
因此,您的硬盘布局可能如下所示
D:\Root
web.config
D:\App1
default.aspx
...
D:\App2
default.aspx
...
创建指向 D:\Root 的根应用程序,然后在该应用程序下创建两个虚拟目录 App1 指向 D:\App1 和 App2 指向 D:\App2。
这两种情况的效果是,您实际上将一个应用程序分为两个部分,两个部分都在同一会话范围内,因此两者的代码可以共享相同的会话数据。
您还必须确保应用程序的应用程序路径在两个 Web 服务器上必须相同。这里有一篇旧文章可能会有所帮助
http://support .microsoft.com/default.aspx?scid=kb;EN-US;q325056
我们目前遇到了类似的问题,只不过我们使用的是 IIS 7.5 并且应用程序路径对我们隐藏(不使用不再是元数据库了)。有谁知道如何使用 IIS 7.5 解决此问题?
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
默认情况下,会话不能在不同应用程序之间共享。据我所知,您有两个不同的应用程序
App1
和App2
,它们在单独的虚拟目录中运行,甚至可能在单独的应用程序池中运行,因此不要期望在它们之间共享会话。与往常一样,您可能会发现一些有用的解决方法。正如您所看到的,它使用 hack(反射)来规避 ASP.NET 团队设计者的决定,即不公开某些类和属性,并使我们作为开发人员的生活变得困难。
By default session cannot be shared between different applications. From what I can see you have two distinct applications
App1
andApp2
which run in separate virtual directories and probably even separate application pools, so don't expect to share session between them.As always there are workarounds that you may find useful. As you can see it's using a hack (reflection) to circumvent ASP.NET team designer's determination to not expose certain classes and properties and make our life as developers difficult.