11

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

DaveDev
  • 41,155
  • 72
  • 223
  • 385
  • did you were able to complete this ? – Oscar Cabrero Jan 26 '12 at 22:13
  • @DaveDev i know i am late to the party :P, but this could help others. if you could find away to share same domain for session cookie(see https://msdn.microsoft.com/en-IN/library/ms228262(v=vs.85).aspx) and store session at common service(DB/Redis) then you could absolutely share session between multiple server – Arjun Vachhani Nov 08 '15 at 14:14

4 Answers4

10

By default session cannot be shared between different applications. From what I can see you have two distinct applications App1 and App2 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.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • You're right that they are distinct applications. One exists in in D:\App1 and the other is in D:\App2, and are in different virtual directories under DefaultWebSite in IIS. However, both are in DefaultAppPool. The reason for this is we will eventually be deploying this app across 3 web servers that need to share the same state. – DaveDev Jul 20 '10 at 17:02
  • I think it's the virtual directory that determines the application name and not the application pool, so I guess you will have to resort to the hack which forces the same application name. – Darin Dimitrov Jul 20 '10 at 17:04
  • Ok, I'll take this into consideration. If we end up going the route of hacks to achieve this result, I think we might be better to stick with the database to store the session. The db approach appears to be more robust anyhow. – DaveDev Jul 20 '10 at 17:05
  • Sorry to disappoint you but even if you take the database solution route you will have to resort to hacks: http://blogs.msdn.com/b/toddca/archive/2007/01/25/sharing-asp-net-session-state-across-applications.aspx There's just no out-of-the-box way to share session between applications in ASP.NET. The out-of-proc session is useful when you have the same application running in a server farm. For different applications you will probably look at a more standard way of sharing data (GET, POST requests). – Darin Dimitrov Jul 20 '10 at 17:07
  • I'm just thinking.. you said it's the virtual directory that determines the application name. This application will be deployed across 3 web servers, each of which are going to have the same Web Site name in their respective IIS, with a load balancer splitting the load between them. Would this qualify as having the same application name? Do you think that it'd work in an environment like that? – DaveDev Jul 20 '10 at 17:23
  • No, it won't qualify as the same application. – Darin Dimitrov Jul 20 '10 at 17:27
  • Ok, thanks for the info on this stuff. I think we'll have to have a think about how we're going to do this. – DaveDev Jul 20 '10 at 17:29
6

Actually you can share sessions using Sql server mode.

Try this:-

I just changed the procedure i.e.

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

and then modified web.config as:-

<sessionState mode="SQLServer" sqlConnectionString="Data Source=.;Integrated Security=True;Application Name=TEST" cookieless="false" timeout="20"></sessionState>
   <httpRuntime targetFramework="4.5"/>

You have to add Application Name and that have to be the same for all the application for which you want to share the same session.

Thanks.

Calyfs0
  • 111
  • 1
  • 11
  • Not only did this work, it's the easiest implementation by far. Thanks! – Nate Kindrew Jul 25 '16 at 15:10
  • Also make sure that your machine keys and App IDs are the same. https://blogs.msdn.microsoft.com/httpcontext/2012/06/22/shared-session-state-in-a-iis6-and-iis7-web-farm/ – chrisp_68 Jan 11 '17 at 16:39
3

Update: Here is a previous post I answered on this same topic Sharing sessions across applications using the ASP.NET Session State Service

As already pointed out, Session data is scoped to the application. That is the Application you create in IIS. So two applications with the same session id will not be sharing the same session because of the application scoping.

As an alternative idea that might or might not be feasible for you. You can create a root application and have the code for D:\App1 and D:\App2 in two subfolders.

d:\Root
  web.config
  \App1
     default.aspx
     ...
  \App2
     default.aspx
     ...

Then in IIS you create an Application pointing to d:\Root.

You can also create an Application in IIS and then under the Application you create two virtual directories, one pointing to D:\App1 and the other to D:\App2, then they can also share a single web.config at the Application level. It is critical that the two virtual directories are just virtual and not created as Applications.

So you harddisk layout might look something like this

D:\Root
  web.config

D:\App1
  default.aspx
  ...

D:\App2
  default.aspx
  ...

Create the root application pointing to D:\Root and then under the application create the two virtual directories App1 pointing to D:\App1 and App2 pointing to D:\App2.

The effect in both cases is that you actually have one application split into two sections, both in the same Session scope therefore the code for both can share the same session data.

Community
  • 1
  • 1
Chris Taylor
  • 52,623
  • 10
  • 78
  • 89
  • I tried to do exactly same, within my main website, i created 2 apps App1 and App2 and both pointing their respective application code, however from App1 when i set session and redirect to App2, App2 doesn't recognize the session. – Abbas Jun 03 '23 at 06:54
  • @Abbas - I have not used ASP.NET in years so I do not know if anything has changed. However, did you create two apps or are App1 and App2 virtual directories under a single App? For the session sharing to work App1 and App2 must not be created as Applications but as virtual directories under a root application using one of the two approaches above. – Chris Taylor Jun 16 '23 at 11:57
2

You also have to make sure that the application path for the app has to be the same on both web servers. There is an old article here that might help

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q325056

We are currently experiencing a similar problem, except that we are using IIS 7.5 and the application paths are hidden to us (does not use the metabase anymore). Does anyone know a way of troubleshooting this with IIS 7.5?

Brian Jones
  • 701
  • 1
  • 6
  • 6