English 中文(简体)
Holding onto items after a postback
原标题:

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.

最佳回答

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.");
        }
    }
}
问题回答

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.

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.

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.

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");
  }
}

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.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Transaction handling with TransactionScope

I am implementing Transaction using TransactionScope with the help this MSDN article http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx I just want to confirm that is ...

System.Web.Mvc.Controller Initialize

i have the following base controller... public class BaseController : Controller { protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (...

Microsoft.Contracts namespace

For what it is necessary Microsoft.Contracts namespace in asp.net? I mean, in what cases I could write using Microsoft.Contracts;?

Separator line in ASP.NET

I d like to add a simple separator line in an aspx web form. Does anyone know how? It sounds easy enough, but still I can t manage to find how to do it.. 10x!

热门标签