Organizations often face challenge of maintaining legacy Classic ASP applications while developing new features in .NET Core. Complete system migration is not always practical solution due to complexity, risk, and cost. In this article, we are going to explore how to implement distributed session management that allows both systems to work together effectively.
Understanding the Architecture
In typical scenario, legacy Classic ASP application serves as main website (e.g., www.company.com), while new .NET Core application runs on subdomain (e.g., app.company.com). Main challenge is maintaining user session across these separate applications. Solution is to implement centralized session management using shared database.
Database Design
Here is simple but effective database structure:
CREATE TABLE [dbo].[DistributedSessions]
(
[SessionId] VARCHAR(50) PRIMARY KEY,
[Username] NVARCHAR(100) NOT NULL,
[UserData] NVARCHAR(MAX),
[LastAccessed] DATETIME NOT NULL,
[CreatedOn] DATETIME NOT NULL,
[ExpiresOn] DATETIME NOT NULL
)
CREATE INDEX IX_Sessions_Username ON [dbo].[DistributedSessions] ([Username])
CREATE INDEX IX_Sessions_Expiration ON [dbo].[DistributedSessions] ([ExpiresOn])
Classic ASP Implementation
Here is helper class for Classic ASP (saved as session.asp):
<%
Class DistributedSession
Private connString
Private sessionId
Private Sub Class_Initialize()
connString = "your_connection_string_here"
sessionId = Request.Cookies("DistSessionId")
If sessionId = "" Then
sessionId = CreateNewSession()
End If
End Sub
Private Function CreateNewSession()
' Generate unique session ID
Dim newId
newId = Replace(CreateObject("Scriptlet.TypeLib").GUID, "-", "")
' Create cookie
Response.Cookies("DistSessionId") = newId
Response.Cookies("DistSessionId").Domain = ".company.com"
CreateNewSession = newId
End Function
Public Function GetUserData()
Dim conn, rs
Set conn = CreateObject("ADODB.Connection")
conn.Open connString
Set rs = conn.Execute("SELECT UserData FROM DistributedSessions " & _
"WHERE SessionId = '" & sessionId & "' " & _
"AND ExpiresOn > GETDATE()")
If Not rs.EOF Then
GetUserData = rs("UserData")
End If
rs.Close
conn.Close
End Function
Public Sub SetUserData(userData)
Dim conn
Set conn = CreateObject("ADODB.Connection")
conn.Open connString
conn.Execute "UPDATE DistributedSessions " & _
"SET UserData = '" & Replace(userData, "'", "''") & "', " & _
"LastAccessed = GETDATE() " & _
"WHERE SessionId = '" & sessionId & "'"
conn.Close
End Sub
End Class
%>
.NET Core Implementation
Create SessionService class in your .NET Core project:
public class DistributedSessionService
{
private readonly string _connectionString;
private readonly IHttpContextAccessor _httpContextAccessor;
public DistributedSessionService(
IConfiguration configuration,
IHttpContextAccessor httpContextAccessor)
{
_connectionString = configuration.GetConnectionString("SessionDb");
_httpContextAccessor = httpContextAccessor;
}
public async Task<UserSessionData> GetUserDataAsync()
{
var sessionId = _httpContextAccessor.HttpContext.Request
.Cookies["DistSessionId"];
if (string.IsNullOrEmpty(sessionId))
return null;
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync();
var userData = await connection.QueryFirstOrDefaultAsync<string>(
@"SELECT UserData
FROM DistributedSessions
WHERE SessionId = @SessionId
AND ExpiresOn > GETDATE()",
new { SessionId = sessionId });
return userData != null
? JsonSerializer.Deserialize<UserSessionData>(userData)
: null;
}
public async Task SetUserDataAsync(UserSessionData userData)
{
var sessionId = _httpContextAccessor.HttpContext.Request
.Cookies["DistSessionId"];
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync();
await connection.ExecuteAsync(
@"UPDATE DistributedSessions
SET UserData = @UserData,
LastAccessed = GETDATE()
WHERE SessionId = @SessionId",
new {
SessionId = sessionId,
UserData = JsonSerializer.Serialize(userData)
});
}
}
Implementation Benefits
This approach provides several important advantages:
- Cost Effective
- Allows continued use of stable legacy system
- Minimizes risk of full migration
- Reduces immediate development costs
- Technical Benefits
- Shared authentication state
- Consistent user experience
- Scalable solution
- Business Benefits
- Gradual migration path
- Maintain business operations
- Lower training costs
Important Considerations
When implementing this solution, remember these points:
- Security
- Use parameterized queries to prevent SQL injection
- Implement proper session timeout
- Encrypt sensitive session data
- Use secure cookie settings
- Performance
- Implement caching where appropriate
- Create maintenance job to clean expired sessions
- Monitor database growth
- Maintenance
- Log session operations for troubleshooting
- Monitor session timeouts
- Regular cleanup of expired sessions
Conclusion
Distributed session management provides practical solution for organizations that need to maintain legacy Classic ASP applications while developing new features in .NET Core. This approach reduces migration risks and costs while providing consistent user experience.
Implementation requires careful planning and consideration of security implications, but benefits often outweigh complexity of setup. Organizations can continue using valuable legacy systems while gradually transitioning to modern technology stack.