I have a repeater control that displays a playlist for my users, this control can sometimes hold say 1000 or more songs. This is a great feature, I was previously using jQuery to do client side sorting, but that has limitations. So I implemented server side sorting which works great, the only issue i am seeing is that when playlist are this long it takes a second or 2 before the postback and sorting is actually started.
I have watched the actions in firebug and done some research and understand that the databound values are not preserved, which makes sence. My question is, When watching in Firebug, it looks like the repeater control removes all the items in the collection before it starts the postback? is this true have others experienced this?
The repeater control ceases to exist entirely between postbacks. The repeater control is called into existance when you make a page request. It is populated, etc. then rendered to the browser. Once done, ASP.NET will delete all the objects on the page (or rather the garbage collector will get them when required. Either way, you can't get them any more).
When the postback happens it has to re-create the entire repeater all over again. There are some mechanisms, such as viewstate, that try to make this as seamless as possible (i.e. recreating controls just as you left them in the previous request) but they sometimes don't work the way you might expect.
Related
I have a page containing a large amount of controls that can trigger postbacks to the server. I know that it is not considered good practice to have a huge amount controls on one page, but the nature of my ASP.NET web application requires it. Seeing that I have a large amount of controls on this page, I make extensive use of UpdatePanels. I am storing ViewState in Session in order to reduce the response size of the page, which works beautifully.
However, with Fiddler I noticed that the 'asyncPostBackControlIDs' after the '__VIEWSTATE' part of the ajax response contains a list of every control of every UpdatePanel that can trigger a postback. This list is huge! It seems that this list doesn't change much per page, and thus it doesn't make sense to download the entire list every time a postback within an UpdatePanel occurs...
Is there any way to store the 'asyncPostBackControlIDs' on server like you can do with ViewState, or otherwise reduce the size of the 'asyncPostBackControlIDs' list?
AFAIK, there is no documented way for storing asyncPostBackControlIDs else where - further, I am very much in doubt if there can be such possibility because most probably those control ids would be required on client side to decide whether to do regular or asynchronous post-back.
You can set ChildrenAsTriggers property of UpdatePanel to false and register controls manually that are actually triggering the post-back - for example, you may have LinkButton/HyperLink that has java-script handler.
Further, perhaps you may able to reduce the list of controls that can cause post-back. For example, you can use anchors(a) instead of linkbuttons/hyperlinks and then set a hidden variable and then simulate a (hidden) button click. On server side, the value of hidden variable would indicate the actual control responsible for post-back. This way, you can have one button that is a post-back control for many other controls.
Finally, you are really a guy who want to have very efficient request/response streams then abandon ASP.NET control model and rather use ASP.NET MVC. Or at less scale, stop using Update Panels for AJAX (they do complete POST of page and almost entire page cycle is executed at server side) and use script services (along with jquery plugins) instead.
Lastly, you need to see the control ids size with the actual response size - for example, 5K long ids within 100K response may not be a large overhead. Reducing those ids would probably give you 5% savings (if possible) but are efforts for the same worth it?
I have an ASP.Net page with two ListBox components, rendered in the browser as <select> lists. I'm using jQuery to move elements from one list to another by manipulating the DOM. I then select all elements with the mouse and postback the form. That way, all the list elements are posted with the form.
When I submit the form, in my button_save() event handler, the Request.Form[<<listbox ID>>] values are correct. However the ListBox controls themselves, specifically their Items collections, do not reflect my changes.
I've also used Fiddler to modify the select items and submit the form. Same as above, the ListBox values are no different, though the Request.Form values are. Would anyone know what's going on or what incorrect assumptions I'm making?
I believe the problem is that the server constructs a ListBox object that is unaware of changes made to the select box on the client side. That is to say, it uses the ASP.NET markup to construct the list of items, rather than the information submitted from the request.
I'm not aware of any workaround to this, other than accessing the Request.Form values directly.
I believe the root issue is: the ListBox's options are stored in the page's viewstate. When you use client-side javascript / jquery to modify the list's contents, those changes are not reflected in the viewstate. Thus, when you postback, ASP.NET uses the viewstate to build the lists for your codebehind, and your client-side changes are lost.
One way to resolve this would be to manipulate the lists' content via postback, instead of client-side (javascript/jquery). By doing it that way, all changes to the listboxes are incorporated into the viewstate, and thus will remain consistent for each postback.
I am a big fan of jquery (much moreso than postbacks or MS-Ajax/partial-postbacks), so I completely understand that this approach may not be very appealing. Unfortunately, it's the only one I can think of right now. Maybe other stackoverflow'ers will have better alternatives.
Larry, in case you haven't found a solution, here is what I would do.
As other fellows stated, since you are changing DOM client-side, the changes are not reflected to ViewState and therefore you cannot access new values from code-behind.
As a solution, you can create a hidden value and set its value to a serialized form of the lists (combined value/text pairs) everytime you change a list with jQuery. Then you can access the hidden value from code behind and finally deserialize it to get all changes. The method is pretty straightforward actually.
I have a dynamically populated ComponentArt:ComboBox with Autopostback property set to true. So every time the selection changes, a postback to server would be fired. Everything seems to work fine except that the lists of all available items are also posted back to the server.
from Firebug:
ComboBox1_Data %3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3E150%20Mile%20House%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAach%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAachen%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAaheim%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAakrehamn%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAalbeke%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAalen%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAalst%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAalter%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3E%C3%84%C3%A4nekoski%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAarau%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAarberg%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAarbergen%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAarburg%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAarebakken%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAarschot%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAarsele%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAartrijke%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAartselaar%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3Cc%3E%3Cr%3E%3Cc%3E%3Cr%3E%3Cc%3EText%3C%2Fc%3E%3Cc%3EAavasaksa%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E%3C%2Fc%3E%3C%2Fr%3E
ComboBox1_Input Aalst
ComboBox1_SelectedIndex 7
As most my clients are using slow connections, this amount of postback has a huge impact on their user experience. Since I'm storing the viewstates in session already, there's really no need for any of the component to restore states from the client. So I'm wondering if this is normal for ComponentArt:ComboBox to do this and not other controls, or this is the normal way of doing things?
Yes, it is normal for a ComboBox to do it.
You need to disable ViewState to get rid of that. That is because the ComboBox puts everything in its ViewState, not just the selection but all its items as well.
Is there a way to avoid postbacks with gridview every time a row is added to it?
In other words, can I store the DataTable on the client and pass it on to the server control when I am done to save, rather than do postbacks every time the row is added?
I searched and searched....all I could find was web services, JSON, and I have a feeling it's redundant here...it's a simple task I am sure everyone had to do at some point.
Can anyone shed some light on this?
There is no avoiding postbacks if you're dealing with a standard ASP.NET GridView that utilizes ViewState.
You can however, disable ViewState and manually (programmatically) render the control on every page load. This will let you control every aspect of row creation/removal/updates, but you'll have to do it all manually. And yes, you'll utilize AJAX to read from or update on the server.
I don't konw of anything that lets you do that with the gridview out of the box, except the UpdatePanel, but that doesn't really count. If you want to implement I a full AJAX grid I would look into using the ListView Control, which will give you much more control over the resulting html.
Heres a great article from MSDN Magazine http://msdn.microsoft.com/en-us/magazine/cc337898.aspx
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 details 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 independent 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?
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:
Initialize
LoadViewState
Load Postback Data
Call control Load events
Call Load event
Call control events
Control PreRender
PreRender
SaveViewState
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?
Some other options:
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.
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.
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.
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