views:

1193

answers:

5

What choices do I have for creating stateful dynamic content in an ASP.Net web site?

Here's my scenario. I have a site that has multiple, nested content regions. The top level are actions tied to a functional area "Catalog", "Subscriptions", "Settings".

When you click on the functional action, I want to dynamically add content specific to that action. For example, when Catalog is clicked, I want to display a tree with the catalog folders & files, and a region to the right for details.

When a user clicks on the tree, I want a context sensitive details to load in the deails region (like properties or options to manage the files).


I started with UserControls. They worked fine as long as I kept loading everything into the page, and never let one disappear. As soon as one disappeared, ViewState for the page blew up because the view state tree was invalid.

(I didn't want to keep loading stuff into my page because I don't want the responses to be too huge)

So, my next approach was to replace my dynamic regions with IFrames. Then instead of instantiating a UserControl, I would just change the source on my IFrame. Since the contents of the IFrames were independant pages I didn't run into any ViewState problems.

But, I'm concerned that IFrames might be a bad design choice, but don't fully understand why. The site is not public, so search engines aren't a concern.


So, finally to my question.

What are my options for this scenario? If I choose an Ajax Solution (jQuery), will I have to maintain my own ViewState? Are there any other considerations I should take into account?

+1  A: 

you've got a number of different options, and yes, IFrames were a bad design choice.

The first option is the AJAX solution. And with that there's not really a viewstate scenario, it's just you're passing data back and forth with the webserver, building the UI on the fly as needed.

The next option is to dynamically add the controls you need for a given post, everytime. The way this would work, is that at the start of the page life cycle, you'd need to rebuild the page exactly as it was sent out the last time, and then dump out all the unneeded controls, and build just those that want.

A third option would be to use Master pages. Your top level content could be on the Master page itself, and have links to various pages within the website.

I'm sure given enough time, I could come up with more, but these 3 appeared just from reading your problem.

Stephen Wrighton
Any answer I gave here would be a different way of saying this. Nice answer.
KevDog
A: 

Can you explain how to remove controls after they have been added dynamically? I'm familiar with adding the controls dynamically, but how do I dump the ones I added during previous post-backs that I don't want any more?

In my first attempt, I created controls in Init, then based on the action, added the control to a PlaceHolder in OnLoad.

Problem is that if you didn't keep loading controls into the PlaceHolder on subsequent post backs, the viewstate complained.

I tried a scheme of loading the previous control, plus the current, but I couldn't figure out how to get rid of the previous control from the 3rd postback attempt.

Jay Mooney
Dynamic controls don't exist on a postback unless you create them. You have to create your controls on _every_ postback. If you don't want a control any more, you just remember not to create it.
Joel Coehoorn
you would be placing all of your controls into a placeholder. Then just call the placeholder.controls.clear which will empty out the control collection for the placeholder control.
Stephen Wrighton
+1  A: 

Controls that are added dynamically do not persist in viewstate, and this is the reason that it doesn't matter if you use AJAX or iframes or whatever.

One possible work-around is to re-populate controls on postback. The problem with this, is the page life-cycle (simplified) is:

  1. Initialize
  2. LoadViewState
  3. Load Postback Data
  4. Call control Load events
  5. Call Load event
  6. Call control events
  7. Control PreRender
  8. PreRender
  9. SaveViewState
  10. Unload

What this means is the only place to re-add your dynamic controls is Initialize -- otherwise posted data (or viewstate information) is not loaded into that control. But often, because Viewstat/postback data isn't available yet in Initialize, your code doesn't have the information it needs to figure out which controls need to be added.

The only other work-around I've found in this situation is to use a 3rd party control called DynamicControlsPlaceholder. This works quite well, and persists the control information in viewstate.


In your particular case, it doesn't seem like there are that many choices/cases. Is it practical just to have all the different sets of controls in the page, and put them inside of asp:placeholder controls, and then just set one to visible, depending on what is selected?

gregmac
My example was over-simplified. It's not possible to have all the controls in memory, that would be too large (>150 options).I have the controls using viewsate (create in init, add to form in load), the problem comes when I try to remove one after a postback.
Jay Mooney
+1  A: 

Some other options:

  1. Content only appears to be dynamic. You load enough controls on the page to handle anything and only actually show what you need. This saves a lot of hassle messing with view state and such, but means your page has a bigger footprint.
  2. Add controls to the page dynamically. You've already been playing with this, so you've seen some of the issues here. Just remember that the place to create your dynamic controls for postbacks is in the Page_Init() event, and that if you want them to be stateful, you need to keep that state somewhere. I recommend a database.
Joel Coehoorn
+1  A: 

dynamic controls and viewstate don't mix well, as noted above - but that is a Good Thing, because even if they did the viewstate for a complex dynamic page would get so bloated that performance would diminish to nil

use Ajax [I like AJAX PRO because it is very simple to use] and manage the page state yourself [in session, database tables, or whatever works for your scenario]. This will be a bit more complicated to get going, but the results will be efficient and responsive: each page can update only what needs to change, and you won't be blowing a giant viewstate string back and forth all the time

Steven A. Lowe