Passing Data between Pages in ASP.NET

If there's one question I see time and time again in the various .NET forums that I frequent, it is "How do I pass data from one page to the next?" in my web application.

Those of you who are .NET veterans will likely be going 'Groan, not another page/data passing post', but I'm going to defend this article by reminding everyone that there was a time when even experts were seeking this knowledge. A little refresher every now and then never hurts anyone!

Why is Passing Data Such a Big Problem?

The web by its very nature is totally stateless. If you request a page, then your browser requests an image that's on that page, those two actions as far as the web server you’re talking to is concerned, came from completely different people/computers/entities or however you want to describe yourself.

If you've ever done any traditional desktop application development, then this will be absolutely alien to you, because in a desktop app every bit of data you maintain is always available to each and every bit of functionality you create.

Because of this "statelessness" many different methods of trying to maintain state in a web application have been devised. Some of these methods are better than others, and it's this fact that tends to trip most newcomers up. Generally they’re not asking how to do it, but rather asking which the best method to use is.

The Best Method for Passing Data between Pages

What is the best method for passing data between pages? The truth is, there isn't one.

The method you use depends very much on your project and any specifics that mean one is more appropriate than others. For example, let's take the session cache; that's the first port of call for many folks because when they research the subject, it's often the first thing that comes to light. But the Session Cache can actually be the source of many problems, especially in a load balanced environment where there are many back end servers which don't actually share physical server instances.  In this case using the Session is particularly bad because you might populate a value on one request and the response might be served from a different server, leading to the value you just saved not actually having a value.

Then there's the timeout issue; session variables (and some others) have an automatic timeout, which means that leave the page for too long and you'll suddenly find that the value you pass doesn't even get saved.

What you absolutely have to do is look at each method in turn and match it up against your project specifications to see which is best.  In fact, in many cases you’re actually better combining some of the methods.  For example, using an external database store needs a key to identify your data, and that key still needs to be passed from page to page in order for following pages to retrieve the actual data.

What Methods are Available for Passing Data?

There are lots of methods available for passing data. I could do an entire series on them with one article per method, and make it last for about six months! For this article, however, we’re going to look at the five or six most common methods.

Method 1 - Url parameter passing

  • Pros : Simple to use, can handle relatively large data loads, works everywhere
  • Cons : Looks ugly, not search engine friendly, very insecure, open to tampering

Example: (setting)

Response.Redirect("Page2.aspx?test=" + txtTestBox.Text);

Example: (Retrieving)

if (!string.IsNullOrEmpty(Request.QueryString["test"]))
{
  lblDefaultData.Text = Request.QueryString["test"];
}
else
{
  lblDefaultData.Text = "NO DATA PROVIDED OR COULD NOT BE READ";
}

If security is in any way of concern in your application then do not use this method.  This is single headedly one of the most common ways that an application is breached. Imagine if you will that instead of a simple text string, you appended say 'userid=2', and I then came along and changed the address in my browser to say 'userid=1' , what might happen?

An alternative to this is to use URL parameters (the method most used by ASP.NET MVC), where the url is formed something like:

http://page2/param1/param2/

This is far more friendly to search engines, but is still very insecure in so much that the values are still visible in plain text, even if it is now harder to see what the variable names are.

If you do choose to use this method, then you MUST make sure that you’re sanitising any inputs thoroughly, and not just any generated by the user; assume that everything you pass using this method is bad or has been tampered with in some way.

For simple use cases, such as linking product pages together or very simple applications such as a static blog, then this will often be a very simple to use method to use, and it scales to multiple servers easily.

Method 2 - Form Posting

  • Pros : Simple to use, can handle very large data loads, works everywhere, the defacto method used for in page forms
  • Cons : can be insecure and open to tampering using tools like fiddler, needs the user to action via a button on page (Can be automated but needs extra JavaScript)

Example: (setting)

<form method="post" action="Page2.aspx">
  <h1>Page passing tests (Method 2 - form post)</h1>
  <p>Please enter some data in the field below and click send</p>
  <input type="text" id="txtTestBox2" name="txtTestBox2" placeholder="enter text here" style="width: 200px;" />
  <button type="submit" id="btnSend">Send</button>
</form>
 

Example: (Retrieving)

if (!string.IsNullOrEmpty(Request.QueryString["test"]))
{
  lblDefaultData.Text = Request.QueryString["test"];
}
else
{
  lblDefaultData.Text = "NO DATA PROVIDED OR COULD NOT BE READ";
}

Without the humble post, nothing on the web would work, this is the mainstay of just about everything that's entered anywhere on any kind of form.  As such it's supported by everything on the planet.

What many people fail to remember however is that ANYTHING inside that set of form tags that has a 'name' attribute will also be sent. Things like hidden input fields, and even the submit button itself. It is by its very nature a manual process though, in so much that you generally have to have a button on the page that the user will click in order to activate the process.

That said, in this day and age it is possible to fire off a post using client side JavaScript, and in fact many of the compatibility layers that provide Ajax support for older browsers do just this, using an IFrame constructed client side, into which a form is built dynamically.  At one point (until all the browsers caught up) this was in fact one of the main ways to achieve Ajax like functionality in a non Ajax enabled browser.

Like a URL parameter, it scales well to a web farm but is still very insecure; all results should ideally be done over HTTPS to protect the in-page payload.  Also note that if you want to do this in a web-forms app, then you need to make sure that there is no outer page form controlled by the web-forms engine when doing so, otherwise it will interfere with your form.

Method 3 - Session Variables

  • Pros : Reasonably simple to use, supported in all versions of IIS/.NET, very secure
  • Cons : Can cause more problems than it solves, doesn't scale well

Example: (setting)

Session["test"] = txtTestBox3.Text;

Example: (Retrieving)

if (!string.IsNullOrEmpty((string)Session["test"]))
{
  lblDefaultData.Text = (string)Session["test"];
}
else
{
  lblDefaultData.Text = "NO DATA PROVIDED OR COULD NOT BE READ";
}

Anyone who's done any kind of ASP.NET (or any web programming for that matter) will know about sessions, there are as many platform specific implementations as there are stars, each one claiming to be the better one of them all.

The problem is, they all have one fatal flaw, they are machine specific, they time out (usually at the wrong time) and they don't scale to well. Additionally, there's often an upper limit to the amount of memory that can be used; too much stored in the session can cause severe performance problems.

On the flip side however, they’re rock solid as far as security goes, they stay on the server so no data ever leaves the server and thus there's nothing to be tampered with client side, and if managed correctly you can overcome most of the problems associated with using them.

On the whole however, I see a lot of folks just using the simple session interface and not managing them correctly, and this is what tends to lead to the problems we see.

For example, look at the code above, you'll see that I have to cast the data type.  You should do this with EVERY access, along with checking for an appropriate value and acting accordingly if no suitable value is present.

Remember also, that the ASP.NET session API can have its providers replaced by custom providers; there are indeed many excellent replacements out there, from things like interfaces to redis and memcache, right through to session stores that are designed to overcome the single machine problem and support a load balanced server farm.

Method 4 - Web Cache

  • Pros : Reasonably simple to use, supported in all versions of IIS/.NET, very secure
  • Cons : Has some similar problems to sessions, not really designed for page passing

Example: (setting)

WebCache.Set("test", txtTestBox3.Text, 10, false); // Cache the value for 10 minutes

Example: (Retrieving)

string test = WebCache.Get("test");
if(!string.IsNullOrEmpty(test))
{
  lblDefaultData.Text = test;
}
else
{
  lblDefaultData.Text = "NO DATA PROVIDED OR COULD NOT BE READ";
}

The web cache is not really designed for passing data from page to page, and it does have some of the same problems that using the session cache does (namely that it's restricted to one machine so doesn't scale to well), memory can be an issue too but not usually as severe as the memory limitation on the session cache, especially if better backend memory cache software is installed on the server in question.

The web cache is more tuned for you to save data from your backend services such as database lookups, so that subsequent calls don't have to make a new roundtrip if data has not been changed.

One plus side on using the web cache is that you can control the timeout value.  You'll see above that I set the timeout to 10 minutes when I set the value.  This timeout can be set to different independent values for each different variable.

One last thing to remember is that web cache storage is accessible by every application instance, so if you cache "test" then other instances of the app running on the same server can also read "test"; this is different from session storage where each key even if the name is the same can be read only by the instance that created it.

Method 5 - Cookies

  • Pros : Very simple to use, the original data passing mechanism
  • Cons : Not secure, not always enabled, frequently cleared by users

Example: (setting)

Response.Cookies["test"].Value = txtTestBox3.Text;

Response.Cookies["test"].Expires = DateTime.Now.AddMinutes(10); // expire in 10 minutes

Example: (Retrieving)

string test;
try
{
  test = Request.Cookies["test"].Value;
}
catch(NullReferenceException)
{
  test = string.Empty;
}
if (!string.IsNullOrEmpty(test))
{
  lblDefaultData.Text = test;
}
else
{
  lblDefaultData.Text = "NO DATA PROVIDED OR COULD NOT BE READ";
}

Using cookies is the original data preservation method, that's been in use since the days of web 0.09. :-)

Unfortunately, cookies have been dramatically abused, to do things they were never intended to be used for, such as user behaviour tracking. As a result the humble cookie now has such a bad name that most people either have them turned off in their browser, or they refuse to accept them. If cookies are accepted however, then they are a really reliable method (and well tested) for preserving data.  Typically though, they are restricted to 4k.

What about the REST?

There's a lot of options we've not even mentioned here. HTML5 for example brings a lot of new cards to the table in the form of data-x attributes, or client side local database storage. There are also server subsystems such as redis and the 'hstore' capabilities of PostgreSQL, or the flat document stores such as MongoDB.

On top of that, in most cases you wouldn't want to restrict yourself to one of the above.  In most general cases, you'll want to use low value storage to store a key of some kind; this key would then be used to look up the stored values using some other method.

You might also want to consider direct client side interaction, where a JavaScript call could be used to persist some values to the server prior to a new page being loaded.  This new page then retrieves these values using some method, and then uses them in a normal fashion to affect the page output.

Page data passing is an immense topic, that can cover entire books, so I'm sure you'll be forgiven if it takes you time to assess all the options you have covering it.

From Here...

If you have any ideas for posts for this series, please reach out to me on twitter '@shawty_ds' or come and find me in the Linked .NET users group (Lidnug) on the Linked-In social network, and remember, the world doesn't need your code, your code needs the world.



Related Articles

Comments

  • Post method

    Posted by Rishi on 07/01/2014 03:49am

    Hi, How can a post method use Request.QueryString? Shouldnt it be Request.Form?

    • RE: Post Method

      Posted by Peter Shaw on 09/26/2014 07:11am

      You can use Request.Form, If the data is passed from a form as part of the page payload. You can ALSO pass data via the QueryString at the same time. There's nothing at all stopping you from passing some data in the post payload AND via the query string at the same time, even if the requst is a POST request. Shawty

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds