JsonQueryStringConverter Class

The JsonQueryStringConverter class comes equipped with the .Net Framework 3.5.  The basic premise here is you can serialize an object into a JSON-like string which can be passed via query string.  Typically this class is to interact via Windows Communication Foundation although it’s interesting to see how it works with a simple application.  I can see using this as a means to serialize and transport object data without going through web services and using SOAP.  You may find a practical application for this today.

Let’s start with a very basic type with some properties to show how this works.  We’ll have one of our properties be another type with properties to show a bit of hierarchy.  Note – your classes must be serializable.  I’ve marked both of my objects with the [Serializable] attribute.  The ToString methods I’ve added are for demonstration purposes to show the data in the objects.  We’ll use them below, but these are not requirements by any means.

[Serializable]
public class MyName
{
      public string First { get; set; }
      public string Last { get; set; }
      public override string ToString()
      {
            return string.Format("First: {0}, Last: {1}", First, Last);
      }
}

[Serializable]
public class MyClass
{
      public MyName MyName { get; set; }
      public string MyAddress { get; set; }
      public int MyAge { get; set; }
      public bool IsOld { get; set; } 

      public override string ToString()
      {
            return string.Format("MyName: {0}, MyAddress: {1}, MeAge: {2}, IsOld: {3}", MyName.ToString(), MyAddress, MyAge, IsOld);
      }
}

 

As you can see we’ve create two types; MyClass and MyName, with MyName being a type used within MyClass.  We’re also using auto-implemented properties.  If you’d like a bit more info on those, check out this short explanation.  Next, we’re going to instantiate an object of MyClass, and convert it to a JSON string for ease of passing over the web.  We’ll do this using the System.ServiceModel.Dispatcher.JsonQueryStringConverter class (you must reference the System.ServiceModel.Web assembly first).

void JsonQuerystringConversion()
{
      //setup object to test with
      var me = new MyClass();
      me.IsOld = false;
      me.MyAddress = "123 My Way";
      me.MyAge = 29;
      me.MyName = new MyName { First = "ian", Last = "suttle" }; 

      //convert object to JSON value
      JsonQueryStringConverter jsonQ = new JsonQueryStringConverter();
      string value = jsonQ.ConvertValueToString(me, typeof(MyClass));
      Response.Write(value);
}

If you compile and run it you’ll see this method create a string as follows:

{"_x003C_IsOld_x003E_k__BackingField":false,"_x003C_MyAddress_x003E_k__BackingField":"123 My Way","_x003C_MyAge_x003E_k__BackingField":29,"_x003C_MyName_x003E_k__BackingField":{"_x003C_First_x003E_k__BackingField":
"ian","_x003C_Last_x003E_k__BackingField":"suttle"}}

That’s great, but we must also be able to revert this data to an object to get the best bang for the buck.  That’s just as easy, if not easier, than what we just did.

void JsonQuerystringToObject()
{
      //convert querystring value to object
      JsonQueryStringConverter jsonQ = new JsonQueryStringConverter();
       //naturally this would come from the querystring and never as a hard-coded string here
      string value = "{\"_x003C_IsOld_x003E_k__BackingField\":false,\"_x003C_MyAddress_x003E_k__BackingField\":\"123 My Way\",\"_x003C_MyAge_x003E_k__BackingField\":29,\"_x003C_MyName_x003E_k__BackingField\":{\"_x003C_First_x003E_k__BackingField\":
\"ian\",\"_x003C_Last_x003E_k__BackingField\":\"suttle\"}}";

      var fromString = jsonQ.ConvertStringToValue(value, typeof(MyClass));
      Response.Write(fromString.ToString());  //This is why we added the ToString method
}

A couple of items to point out as the inline documentation already does:a) we’d never have value in hard-coding the JSON string into the code like this and would likely grab it from the Request object 
b) the last line of this method uses the ToString method we added to display the values in the MyClass object.
And the result: 

MyName: First: ian, Last: suttle, MyAddress: 123 My Way, MeAge: 29, IsOld: False

Bingo – the JSON string was successfully converted back into a MyClass object, with the MyName property being created properly as well.

 

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

VS 2008 Orcas and .Net 3.5 Beta 2 Released

Scott Guthrie has officially announced the Beta 2 release of Visual Studio 2008 and the .Net Framework 3.5.  You can see additional information on Scott Guthrie's blog.  You can download the full version of Visual Studio 2008 here or get Visual Studio 2008 Express Editions here.

Among the various improvements offered, I'm pleased to see Unit Testing is now a part of the Professional version and not exclusive to Team versions only.  Pro's a bit lighter on the pocket book Tongue out.

I've had great success with Beta 1 to date, so I'm quite excited to jump into Beta 2.  If you're like me, you'll need to follow both the recommended installation notes in Scott's blog entry; one for all installations of Beta 2, and the second for users who have previous installations.  If you have any additional information you'd like to share regarding VS 2008 Beta 2, please do!

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Implicitly Typed Local Variables

C# 3.0 introduces  implicitly typed local variables by way of the keyword “var”.  The use of var allows one to assign a number of different types to a variable without explicitly stating that variable’s type.  Var is actually not a type at all, but a keyword which instructs the compiler to infer the most appropriate type based on the value or expression to the right of the equals sign. If you’ve developed in the pre-.Net ASP languages you might be inclined to think of var as “Variant” - but don’t J.  Forget everything you’d previously learned about variant types as var is not even a loosely or late-bound type; it no longer applies.

Let’s compare apples to apples here.

In C# 2.0 we would declare variables in a method in this manner:

void MyMethod()
{
    int x = 5;
    string name = “ian”;
}

This type of declaration makes it quite obvious what a variable’s type is, and the value it will contain. 

Using var in C# 3.0:

void MyMethod()
{    
    var x = 5;
    var name = “ian”;
}

As you can see above the use of var is indeed syntactically a bit faster, and offers a variable the ability to receive an unknown (at design time) value type.  You really get what you pay for however.  Even though var has its place with LINQ, it would seem abuse of the keyword for standard variable usage could lead to ambiguity when reading or supporting the code.  One major plus on this note, I found if I assign var x = 5, VS knows it’s an int at design time.  If I then change this to be var x = 5 * 1.2452, VS recognizes it as a double at design time.  Quite impressive!

What are the constraints of using implicitly typed local variables?  Here’s a quick list:

- Must be declared within a method
- Cannot be passed as arguments to other methods
- Can be used in “for” initialization:
     - for (var x = 0; x < myArray.Length; x++) …
- Can be used in “foreach” initialization:
     - foreach (var item in myItems) …
- Can be used in a “using” statement:
     - using (var cmd = db.GetStoredProcCommand("_usp_AccountDelete"))…

Lastly, C# 3.0 also provides for implicitly typed arrays, and is a key player in LINQ utilization.  More on that soon.

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Auto-Implemented Properties

.Net Framework's Auto-Implemented Properties, also known as Automatic Properties, are a nifty way of saving a few lines of code without sacrificing performance.  Previous to .Net 3.5 one would typically write a property as follows (C#):

string _name = string.Empty;
public string Name
{
     get { return _name; }
     set { _name = value; }
}

Let's pretend creating the local variables to hold our simple property value is mundane (okay, it is).  Wouldn't it be oh so nice to cut this down to the following code:

public string Name { get; set; }

public string Country { get; private set; } //creates a read-only property

Well you're in luck because that's all there is to it!  When this code is compiled, the compiler will output equivalent logic to the pre-.Net 3.5 property.  Naturally this isn't practicle if you want to modify the private/protected value vs. the public value, but for the basic property such as one you may find in an entity class, Auto-Implemented Properties are quite useful.

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Applying AJAX Using ASP.NET 1.1

[Download Project Files] [View Sample]
Introduction
You’ve heard of it. It is the latest buzz term for web programmers these days. AJAX is an acronym that stands for Asynchronous JavaScript and XML. AJAX gains its popularity by allowing data on a page to be dynamically updated without having to make the browser reload the page. I will describe more about how AJAX works, and then go into some sample code to try out.

This term has been made famous by some of Google’s latest web apps. At the top of this list is Google Suggest, which gives you suggestions (go figure) on what you are searching for as you type based on popularity of the search term. If you aren't familiar with Google Suggest, check it out.

There is more going on here than just AJAX however. The actual drop down list is an additional DHTML piece that we will not be covering in this article.

Is AJAX a new technology? Yes and no would both be incorrect answers. A proper answer would be a new application of current technologies, with emphasis on plurality. This list of technologies includes standard HTML controls, JavaScript, an XML HTTP component, and XML data structures.

 
The Steps
The following is an outline of the sequence of events when using AJAX:
  1. Web page is rendered
  2. A trigger executes a JavaScript function call (i.e. onKeyUp, button click, setTimeout, page load, etc.)
  3. JavaScript instantiates an XML HTTP object
  4. XML HTTP object calls a remote page
  5. Remote Page transforms an XML structure using XSLT and returns the result
  6. JavaScript accepts the results and applies it to the page
  7. Tada! No page reload, just magical dynamic data
Get To It Already!
These steps are great, but without a sample application it is tough to envision. Being the responsible author that I am, I have of course included a sample of the steps discussed.

I think that it is important to discuss the XML HTTP object to gain a better understanding of what is going on here. XML HTTP allows code to connect to a remote location and perform GET and POST requests asynchronously. This means that we can connect to a remote host, send a request, and continue on with additional logic. When the remote host returns a response, a function designated to handle the return event is able to accept the data and make decisions based on what was received. The data passed to and from the remote host does not have to be in an XML format. XML is simply a well-formatted string. I have found on multiple occassions that passing a string that is not in an XML format is most appropriate for the given task. The XML HTTP object will not be compatible on all browsers or operating systems. Being that this is a client side function the client machine is responsible for the implementation as opposed to the server.

I have been utilizing this object since ASP 3.0 for making remote calls from a web page. Imagine the power here. Data and processes are accessed on disparate locations without the client ever having to leave the comfort of the domain or page that he/she is on.

 
The JavaScript
The JavaScript is the real meat and potatoes in AJAX. It handles the change detection, data request and receipt, and placing the data on the page.

Be sure to update the requestURL variable with the path that you will be accessing the aspx file from.

The following is the JavaScript code used:

<script>
    var xmlHttp;
    var requestURL = 'http://localhost/misctest/getusernames.aspx?q=';
    var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
    var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5")!=-1) ? 1 : 0;
    var is_opera = ((navigator.userAgent.indexOf("Opera6")!=-1)||(navigator.userAgent.indexOf("Opera/6")!=-1)) ? 1 : 0;
    //netscape, safari, mozilla behave the same???
    var is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;

    function show_data(strName){
        if (strName.length > 0){
            //Append the name to search for to the requestURL
            var url = requestURL + strName;
            
            //Create the xmlHttp object to use in the request
            //stateChangeHandler will fire when the state has changed, i.e. data is received back
            // This is non-blocking (asynchronous)
            xmlHttp = GetXmlHttpObject(stateChangeHandler);
            
            //Send the xmlHttp get to the specified url
            xmlHttp_Get(xmlHttp, url);
        }
        else {
            //Textbox blanked out, clear the results
            document.getElementById('nameList').innerHTML = '';
        }
    }

    //stateChangeHandler will fire when the state has changed, i.e. data is received back
    // This is non-blocking (asynchronous)
    function stateChangeHandler()
    {
        //readyState of 4 or 'complete' represents that data has been returned
        if (xmlHttp.readyState == 4 || xmlHttp.readyState == 'complete'){
            //Gather the results from the callback
            var str = xmlHttp.responseText;

            //Populate the innerHTML of the div with the results
            document.getElementById('nameList').innerHTML = str;
        }
    }

    // XMLHttp send GET request
    function xmlHttp_Get(xmlhttp, url) {
        //Getting a permissions error here? Check the url string to
        // ensure it is accurate (defined above)
        xmlhttp.open('GET', url, true);
        xmlhttp.send(null);
    }

    function GetXmlHttpObject(handler) {
        var objXmlHttp = null;    //Holds the local xmlHTTP object instance

        //Depending on the browser, try to create the xmlHttp object
        if (is_ie){
            //The object to create depends on version of IE
            //If it isn't ie5, then default to the Msxml2.XMLHTTP object
            var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';
            
            //Attempt to create the object
            try{
                objXmlHttp = new ActiveXObject(strObjName);
                objXmlHttp.onreadystatechange = handler;
            }
            catch(e){
            //Object creation errored
                alert('IE detected, but object could not be created. Verify that active scripting and activeX controls are enabled');
                return;
            }
        }
        else if (is_opera){
            //Opera has some issues with xmlHttp object functionality
            alert('Opera detected. The page may not behave as expected.');
            return;
        }
        else{
            // Mozilla | Netscape | Safari
            objXmlHttp = new XMLHttpRequest();
            objXmlHttp.onload = handler;
            objXmlHttp.onerror = handler;
        }
        
        //Return the instantiated object
        return objXmlHttp;
    }

    function UseValue(strVal){
        document.frmStuff.txtName.value = strVal;
    }
</script>
 
The Client Page (HTML)
The client page, excluding the JavaScript, is about as basic as it gets. A simple form with an onKeyUp event in a text box is all that is really required.  I included a DIV tag to display the resulting data.  The HTML has been provided:
<html>
<head>
<title>Ian Suttle's AJAX Sample</title>
    <style>
        body, input {font-family: arial; font-size: 12px;}
    </style>

    <!-- Insert JavaScript Here -->

</head>
<body>
    <form name="frmStuff" id="Form1">
        <table border="0" cellpadding="4" cellspacing="0" id="Table2">
            <tr>
                <td width="100">Name:</td>
                <td><input type="text" name="txtName" id="txtName" autocomplete="off" onkeyup="show_data(this.value);"></td>
            </tr>
            <tr>
                <td width="100" valign="top">Suggestions:</td>
                <td>
                    <div id="nameList"></div>
                </td>
            </tr>
        </table>
    </form>
</body>
</html>
 
The Remote Page
When a request is made from the JavaScript, it makes contact with the “remote page.” A query string variable, “q”, is included representing the data that was keyed by the user. I am going to construct an XML string, only including those elements that are valid based on the search term. To relieve the client side script from doing any formatting, I have applied an XSL transformation on the XML data. Formatting the XML on the server side is a much better solution than formatting within the JavaScript on the client side. A major point to recognize is that certain browsers will not support XML and XSL objects. Assuming you want your data to always be formatted the same, stick with the server side logic.

Create a page called GetUsernames.aspx. Be sure to remove ALL HTML from the page except the required @Page line. The code-behind will create the output to display on the page. Add the following code to the code-behind file:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;

namespace MiscTest
{
    /// <summary>
    /// Summary description for GetUsernames.
    /// </summary>
    public class GetUsernames : System.Web.UI.Page
    {
        private void Page_Load(object sender, System.EventArgs e)
        {
            GetUsernameList();
        }

        #region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
        }
        
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.Load += new System.EventHandler(this.Page_Load);
        }
        #endregion

        private void GetUsernameList()
        {
            //Get the request query
            string strQuery = Request["q"].ToString();

            //Create the XML-like string to be sent back to the request
            string strXmlNames = "";
            
            //An arbitrary array of names that will be written to an XML Document.
            string[] arrStrNames = new string[5]{"Ian Suttle", "John Doe", "Alex Wright", "Albert Einstein", "Sierra Tracy"};

            //Loop through the names, creating a psuedo XML element for each
            foreach(string strName in arrStrNames)
            {
                //If the request matches the beginning of a name, then add it to the string
                // otherwise it shouldn't be a valid match
                if (strName.Length >= strQuery.Length && strName.ToLower().Substring(0, strQuery.Length) == strQuery.ToLower())
                    strXmlNames += "<user><name>" + strName + "</name></user>";
            }

            //Prepend and append the parent element
            strXmlNames = "<?xml version=\"1.0\" ?><users>" + strXmlNames + "</users>";

            //Create an XmlDocument object to store the XML string that we created
            XmlDocument xDoc = new XmlDocument();
            xDoc.LoadXml(strXmlNames);

            //Create a navigator object to use in the XSL transformation
            XPathNavigator xPathNav = xDoc.CreateNavigator();

            //Create the XSLTransform object
            XslTransform xslt = new XslTransform();
            xslt.Load(Server.MapPath("Names.xslt"));

            //Do the transformation and send the results out to the Response object's output stream
            xslt.Transform(xPathNav, null, Response.OutputStream);
        }
    }
}
 
The XSL Stylesheet
The XSL document is used to format the XML data to a defined presentation. The code to do the transformation is included here, although great detail on how this works is not the topic of this article. Create a new XSL document called Names.xslt and paste the following code into it:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:for-each select="users/user">
            <xsl:value-of select="name" /><br />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
 
Conclusion
So once again, AJAX is nothing more than an application of technologies that have been around for a number of years. ASP.NET isn’t the wizard behind this curtain. There is nothing here that can’t be done in ASP Classic and JavaScript. Not that given a choice one would revert to ASP Classic :). Additionally, ASP.NET 2.0 will have a completely different approach to making remote calls from a page.

The possible implications of AJAX are very impressive. Updating notices, checking email, monitoring processes, etc… The limits of application are virtually up to the imagination of the developer.

 
You can read more about Ian Suttle at http://www.iansuttle.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Secure Session State Transfer Between ASP Classic and ASP.NET

 
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:

  • ASP.NET function calls an ASP Classic page
  • ASP Classic page dynamically builds an XML structure to represent the ASP Classic Session State contents
  • ASP.NET loads the XML output, and loops through each element, creating ASP.NET Session variables
 
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
     'If the session contents have a value, we need to URLEncode it to avoid
     ' illegal character sequences. i.e. " & " causes an invalid whitespace
     ' error
     if len(session.Contents(item)) > 0 then
          encItem = server.URLEncode(session.Contents(item))
     else
          encItem = session.Contents(item)
     end if

     response.Write "<" & item & ">" & encItem & "</" & 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()] = System.Web.HttpUtility.UrlDecode(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
          'If the session contents have a value, we need to URLEncode it to avoid
          ' illegal character sequences. i.e. " & " causes an invalid whitespace
          ' error
          if len(session.Contents(item)) > 0 then
               encItem = server.URLEncode(session.Contents(item))
          else
               encItem = session.Contents(item)
          end if

          response.Write "<" & item & ">" & encItem & "</" & 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.
 
Updates
11/26/2004 - Updated to URLEncode and URLDecode contents of the session to avoid XML illegal characters such as "& ".
 
Summary
In this article you have seen how to create a very powerful and secure workaround to transfer session information between ASP Classic and ASP.NET. The solution can be manipulated a million different ways to conform to your needs. The most important thing to remember is that what we just did is impossible :).

You can read more about Ian Suttle at http://www.iansuttle.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

About Me

I'm Ian Suttle and I work for IGN Entertainment, a division of Fox Interactive Media.

Recent posts