I was discussing Session State interoperability between ASP Classic and ASP.NET with one of my developers. Obviously Microsoft did not provide us, the developer community, with a means of making our ASP.NET applications backwards compatible with ASP Classic. I had come up with a couple of ways to achieve this goal. In running a couple of searches on the subject to see how others had conquered the beast, I came across an article by Peter Bromberg entitled "Transfer Session Variables from Classic ASP to ASP.NET" that described in detail exactly how one of my ideas would work.
In reading his article, like Peter, I was amused to see that so many people had declared this task "impossible!" I am writing this example to give you another possibility for the impossible. This article differs from Peter's in that I will explain how to do the Session State transfer without involving the client, offering an additional level of security (yes, it's important) and automation.
To summarize, the logic would work as follows:
| ||
The Code | ||
The ASP Classic code: | ||
<title>ASPClassicSession.asp</title>
<% ' ASPClassicSession.asp will create the XML structure to be gobbled up by ASP.NET
'set the content type to be of type text/xml
response.ContentType = "text/xml"
'begin writing the xml structure
response.Write "<?xml version=""1.0"" ?>" response.Write "<session>"
'loop through the session contents, writing each item as if it were an XML element
for each item in session.Contents response.Write "<" & item & ">" & session.Contents(item) & "</" & item & ">" next
'end the xml structure
response.Write "</session>" %> | ||
The preceding page would output a page similar to the following: | ||
<?xml version="1.0" ?> <session> <UserID>87248</UserID> <Email>ian@iansuttle.com</Email> <UserName>isuttle</UserName> </session> | ||
The ASP.NET (C#) code behind code: | ||
using System.Xml;
using System.Text; using System.Net; using System.Net.Sockets;
...
private string RetrieveXML(string server, string page, System.Web.HttpRequest request)
{ /********************************************** * Send the request **********************************************/
//create socket
IPHostEntry ipHostInfo = Dns.Resolve(server); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint ipe = new IPEndPoint(ipAddress, 80); Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//connect socket to server
socket.Connect(ipe);
//Create the request to send to the server
string strRequest = "GET /" + page + " HTTP/1.1\r\n" + "Host: " + server + "\r\n" + "Connection: Close\r\n" + "Cookie: " + request.Headers["Cookie"] + "\r\n" + "User-Agent: " + request.Headers["User-Agent"] + "\r\n\r\n";
//Convert send data to bytes
Byte[] bytesSend = Encoding.ASCII.GetBytes(strRequest);
//Send the data to the server
socket.Send(bytesSend, bytesSend.Length, 0);
/**********************************************
* Receive the return data **********************************************/
//Declare variables for data receipt
byte[] bytes = new byte[256]; int nBytes = 0; string receive = ""; string xml = "";
// The following will block until the page is transmitted.
do { nBytes = socket.Receive(bytes, bytes.Length, 0); receive += Encoding.ASCII.GetString(bytes, 0, nBytes); } while (nBytes > 0);
//We have the page data, but it includes the headers
// Retrieve XML data from page response xml = receive.Substring(receive.IndexOf("<?xml"), receive.Length - receive.IndexOf("<?xml"));
//Cleanup the socket
socket.Shutdown(SocketShutdown.Both); socket.Close();
//Return the data
return xml; }
public void TransferSession(System.Web.HttpRequest request, System.Web.SessionState.HttpSessionState session)
{ //Clear the session contents to have a clean session - Optional session.RemoveAll();
//Define the URL and page to load the Session XML from
string XMLServer = request.ServerVariables["SERVER_NAME"]; string XMLPage = "aspclassicsession.asp";
//Define an XMLDocument to allow easy XML tree navigation
XmlDocument doc = new XmlDocument();
//Load the document from the reader
doc.LoadXml(RetrieveXML(XMLServer, XMLPage, request));
//Loop through the Session element's child nodes and set
//each Session object foreach(XmlNode node in doc.FirstChild.NextSibling.ChildNodes) { session[node.Name.ToString()] = node.InnerText.ToString(); } } | ||
On execution of the Page_Load function, the TransferSession function gets called, which consumes the XML data from the ASPClassicSession.asp page, creates the Session contents in ASP.NET, and redirects the user to the specified destination page.
Gathering the XML data is not as easy as it sounds. Since the call from the client browser is going to the server, the server is then making the request for the ASP Classic page to generate the XML. The ASP.NET application does not share your ASP Classic Session State. The relationship between your browser and IIS is dependent on specific headers being passed back and forth. In this example we have ASP.NET gather the headers from the client request, and create our own socket connection to the server using our customized headers to create the illusion that we are the client browser making the request. ASP Classic accepts the request and gladly returns the desired results.
With all applications, you must know your data. The current implementation of this solution will not handle objects or arrays. It would not be difficult to customize the solution to work with specific objects if you know how to detect and rebuild them.
| ||
Security | ||
This is a subject often skipped due to lack of education or lack of time. Security is out of the scope of this article, but I will present some ideas. This solution has both inherent security and the ability to apply additional security with minimal effort.
Inherent security exists in that execution occurs on the server-side. A user cannot create their own form or edit post variables to choose a different User ID or security level to transfer to.
What if you don�t want your users to have the ability to request the XML feed and see their session variables? Simply identify servers, such as the ASP.NET web servers, that are allowed to request the file and authorize them on your page. A visual should shed some light on this. I will modify the ASP Classic code from above:
The ASP Classic code:
| ||
<title>ASPClassicSession.asp</title>
<% ' ASPClassicSession.asp will create the XML structure to be gobbled up by ASP.NET
'Modify the IP address to reflect your allowed server IP(s)
If request.servervariables("REMOTE_ADDR") = "127.0.0.1" then 'Authorized
'set the content type to be of type text/xml
response.ContentType = "text/xml"
'begin writing the xml structure
response.Write "<?xml version=""1.0"" ?>" response.Write "<session>"
'loop through the session contents, writing each item as if it were an XML element
for each item in session.Contents response.Write "<" & item & ">" & session.Contents(item) & "</" & item & ">" next
'end the xml structure
response.Write "</session>" else 'Not Authorized
response.write "You are not authorized to view this page"
response.end end if %> | ||
To further secure the data, put it through an encryption / decryption process. |
Secure Session State Transfer Between ASP.NET and ASP Classic
Subscribe to:
Posts (Atom)
No comments:
Post a Comment