views:

126

answers:

6

I have an ASP.NET web application and I want to be able to take items from a master list and store them temporarliy into one of four other lists. The 'other' lists need to survive post backs so that more items can be added to them. What direction would you suggest going with?

I have thought of using a generic list stored in memory, temporarliy storing the items into the database and calling them back on PostBack, or storing them into the viewstate, but I have a feeling that there is some solution that I'm missing that might be easier or better.

A: 

The database Idea is likely a poor one (assuming you're not dealing with large amounts of data).

Perhaps your best method would be to store the main list in ViewState, and have the other lists be lists of indexes to the first list.

Gregory
A: 

The lists should automatically store the values they have in the viewstate. If they don't, you probably need to turn the viewstate on for these controls.

If you manually want to make the data survive the round trip, you can either store them in the session or in the viewstate yourself. Technically the viewstate makes the most sense, but if there's a lot of data, it can make the viewstate very large and take a long time to do a round trip. The only issue with the session is you'll have to make sure you clear it once you leave the page.

Don't use the database, that's not what its for.

Soviut
So far the viewstate is pretty large. I'm a little worried about shoving even more raw data in there than I have to.
Chris
A: 

You could store the list in ViewState or Session and assign it to a property. Here's simple example using a generic list of string, but can be any serializable type.

private List<String> MyTempList
{
   get{return Session["mylist"] as List<String>;}
   set{Session["mylist"] = value;}
}

protected void Page_Load(object source, EventArgs e)
{
  if(!IsPostBack)
  {
     MyTempList = new List<String>();
  }
  else
  {
     MyTempList.Add("Something");
  }
}
ichiban
+1  A: 

The first thing I would suggest is to see if you can remove the need of keeping state across postbacks.

If you can't do so (and ViewState is not applicable for some reason like bandwidth limitations or requiring data preservation even without a postback from a server form), I suggest consider using Session. You can configure session state to use a SQL Server database backend whenever you want without worrying about changing source code.

Mehrdad Afshari
Unfortunately keeping state across postbacks is one of the things that I have to have to accomplish the features I’m working on.
Chris
A: 

All of those are options and all have pro's and cons:

Database:

Storing items in the database is a fairly easy and consistent option. You do have to worry about making a round trip call to the database, but at least you have a centralized location to story the data that will scale easily with your web load. However, if this is short lived data, then you will have to worry about cleaning up your database as it might begin to get unwieldy.

Session/Cache:

Session affords a quick solution for in memory storage, but scaling can become problematic if the amount of data is very large. The more information you store in memory the less capacity you have for concurrent users. Also, if you start to add multiple web servers, then you will have to look into some sort of session state server to make sure users don't spontaneously lose their session.

Cache has basically all the same pros/cons except that there is the additional complexity of having to make sure you expire cache items, and manage concurrency issues.

Again, these are both easy to implement solutions, but don't scale as well under heavy load, or large amounts of data.

ViewState:

Viewstate is also an easy to implement solution and gets the load off the server and into the client, but can result in longer load times for the end user. Also it is important to remember that ViewState can be hacked, so if security is a concern then you want to take extra precautions to ensure data integrity.

Conclusion:

All in all, figure out what you want to accomplish and choose the solution that best fits your needs. Shove it behind some abstraction layer like an interface so you can easily change the details later, and then you won't have to worry as much. It's all about knowing what will work best in your particular scenario.

Josh
+1  A: 

Josh laid out the states pretty well. My recommendation for a smaller list like he said would be using Session state. Using the DB would be a little messy because you have to maintain those temp tables and worry about multi-session access to the tables. Likewise, cache have the same problem. Viewstate gives you this with extra client traffic and insecure data. So if you're talking less than a few thousand instances on a low traffic server, then session is likely fine.

To make session easier to work with (and you can do this with caching and application state as well) is setup a container object that manages the lists.

//To use it in your page, you can easily access it via: 

ListManagerContext.Current.MasterList.Add(4);


[Serializable]
public class ListManagerContext
{
    public List<int> MasterList { get; set; }
    public List<int> SubList1 { get; set; }
    public List<int> SubList2 { get; set; }
    public List<int> SubList3 { get; set; }


    /// <summary>
    /// Key used for the list manager context session variable.
    /// </summary>
    public const string ListManagerContextKey = "ListManagerContext";

    /// <summary>
    /// Gets the current ListManagerContext for this session. If none exists, it returns a brand new one. 
    /// </summary>
    [XmlIgnore]
    public static ListManagerContext Current
    {
        get
        {
            HttpContext context = HttpContext.Current;

            if (context != null && context.Session != null)
            {
                ListManagerContext data = null;
                if (context.Session[ListManagerContextKey] == null)
                {
                    data = new ListManagerContext();
                    context.Session[ListManagerContextKey] = data;
                }
                else
                    data = context.Session[ListManagerContextKey] as ListManagerContext;

                return data;
            }
            throw new ApplicationException("No session available for list manager context.");
        }
    }
}
Nathan
oh... btw. if you're VS 2005, you'll need to fully define your properties. The lazy way will only work in VS2008 and higher.
Nathan
Had to modify a few things here and there, but overall this worked for my issue.
Chris