I am having a problem in which two controls which are added programmatically are trying to load each other viewstate, I want to clear the viewstate before loading the controls, I tried Viewstate.Clear but it did nothing, when I disable viewstate on the container of my controls everything works fine except that the control's state is not kept. Is there a way to clear viewstate of just a specific control?
From your description, it would seem that you are making one of the common mistakes when loading your dynamic controls - either you are loading them too late or you are not assigning them unique IDs (and assigning them the same unique id each time a postback occurs).
If this is indeed your problem, then clearing the viewstate is not the appropriate action to be taking. It is quite simple to fix, check these three links:
http://msdn.microsoft.com/en-us/library/ms972976.aspx
https://web.archive.org/web/20210330142645/http://www.4guysfromrolla.com/articles/092904-1.aspx
http://geekswithblogs.net/shahed/archive/2008/06/26/123391.aspx
Yes ,
string controlName = "name of control";
ViewState[controlName] = null;
// create control, add it to the page
If ViewState gets in your way and you haven't done so already, please read
TRULY understanding ViewSate
It will make you much more comfortable in working with ViewState and the whole ASP.NET page lifecycle.
Assuming both controls inherit from System.Web.UI.Control. You can disable their individual ViewStates by setting their EnableViewState to false. Also you can clear their ViewState, as each control has a ViewState property.
Make sure the id's of the two programmatically added controls are different and the ViewState problem should go away.
You can disable viewstate on a specific control:
EnableViewState="False"
Related
I'm trying to build a very specific search page for a project and I'm having lot of trouble dealing with multiple postbacks invoked by dynamically-generated controls on a single page.
The page has to work like this:
There is a single checkbox, "Detailed search", that causes a postback on checking/unchecking.
When detailed search is not active, a simple grid with contents and buttons is displayed. Nothing special.
When detailed search is active, N checkboxes must be generated from some dynamic data, that represent the sections where you want the search to happen. Below the checkboxes, an AJAX-enabled tab control will appear, initially with no tab pages.
When checking one of the section checkboxes, a postback will occur. After the postback, data will be searched in the section selected by the user, then a new tab page containing a grid view of results and the name of the section will be added to the tab control. If the checkbox is unchecked, the tab page will disappear from the control, again, after a postback.
Now, the issue is that pretty much everything has to be generated dynamically, and that pretty much everything is connected to something else.
First issue: dealing with the "Detailed search" checkbox. Sounds easy, doesn't it? My initial idea was to set Page.Viewstate["DetailedSearchEnabled"] to true or false during the check/uncheck event handler, then create controls dynamically checking the value of DetailedSearchEnabled during Page_Load.
Nope. The postback event-handling happens between Page_Load and Page_LoadComplete. It would take an additional refresh for things to work as intended.
<< Then I'll just generate the controls on Page_LoadComplete! >>
Nope. Those controls need event handling as well, and if they're generated after Page_Load they will not be wired up correctly.
A possible solution would be generating everything in advance, on Page_Load, and only hiding/showing controls on Page_LoadComplete. But that is inefficient, and one important point of this search page is that only the minimum amount of controls should be generated.
The difficulty of this task seems to come from the way event wiring and the page life cycle work.
Surely there must be a better way of approaching this problem.
First issue: dealing with the "Detailed search" check box.
The correct approach (if you want to use page post-backs) is as follows:
In the CheckChanged event handler, save the value of the Checked property to ViewState["DetailedSearchEnabled"]. If the value is true, add the dynamic check boxes to the page. If the value is false, find and remove them.
Override LoadViewState. After calling base.LoadViewState, re-create the dynamic check boxes and wire up their events if ViewState["DetailedSearchEnabled"] is true. Note that neither Page_Load nor Page_LoadComplete is the appropriate place to do this.
Yes, you should create the dynamic check boxes at two points in the page life cycle. I recommend a helper method.
In general, your event handlers should add or remove just the dynamic controls (if any) affected by those particular events, but LoadViewState should re-create all dynamic controls that existed from the previous page request. You must store enough information in view state for LoadViewState to do so.
My answer to this other question demonstrates how to add and remove dynamic controls. You may want to use it as a reference.
Sounds to me like you should be using a CheckBoxList control to handle your dynamic checkboxes. You can add an remove items to the CheckBoxList during your post back and not have to worry about dynamically adding/removing actual controls/events to the form.
Here is a link to the msdn:
https://msdn.microsoft.com/en-us/library/14atsyf5(v=vs.85).aspx
Here is some sample code:
Protected void Button1_Click (object sender, System.EventArgs e)
{
CheckBoxList.Items.Add(new ListItem("TextValue1", "Value1"));
CheckBoxList.Items.Add(new ListItem("TextValue2", "Value2"));
}
If all else fails, you could still fall back on the quick-and-dirty old-fashioned ASP way.
Use Response.Write or <%...%> to generate your dynamic controls as plain old HTML (simple form fields, e.g. <input type="checkbox" name="foo" value="1" />).
Make sure you have a form field for every piece of information you may need after the postback(s). If necessary, use hidden form fields to 're-post' values across subsequent postbacks.
After postback, retrieve the values of the controls with the Request object.
Use those values to adjust the generation of controls as you see fit.
You should be able to do all of this in Page_Load. The advantage is total freedom. The disadvantage is total freedom to make a big mess of your aspx. So you may want to migrate all this dirty code out of your aspx, and into a custom-made control, which you can then add to your aspx.
When generating your own HTML, be careful not to introduce XSS vulnerabilities. Use HtmlEncode where necessary.
As you suggested yourself, there is a better way to tackle it.
If I was in the same situation, I would create web methods for interacting with the page, and use client side to do the UI. I'm currently working mostly with angular JS, although it does come with a learning curve. You could use ng-hide/ng-show to bind to the checkbox event to display the detailed search. When the n number of checkboxes needs to be displayed, you can then just fill them in with ng-repeat, for each of the items you need to display, after a check/uncheck you can dynamically populate new controls etc. through web method calls if extra data is needed.
Pure ASP postbacks are quite clunky from my experience, and not really suited for building a maintainable dynamic UI.
Instead of making so many postbacks, it would be better to use jquery and ajax calls to load the controls as needed and then attach events to it or you can even use UpdatePnael for that. Help Links:
https://www.simple-talk.com/dotnet/asp.net/ajax-basics-with-jquery-in-asp.net/
http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
I am already storing the viewstate in session. However when I use updatepanel, I still see this:
|0|hiddenField|_EVENTTARGET||0|hiddenField|_EVENTARGUMENT||0|hiddenField|_LASTFOCUS||72|hiddenField|_VIEWSTATE|/wEPZwUPOGQwMTViZDAyYzljM2RiDkOzqPgrsrLq7oLjMrtEqvksOkereJ+iwT7JWm4o3eY=|1|hiddenField|_SCROLLPOSITIONX|0|1|hiddenField|_SCROLLPOSITIONY|0|2524|hiddenField|__EVENTVALIDATION|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|0|asyncPostBackControlIDs|||0|postBackControlIDs|||102|updatePanelIDs||tctl00$Body$updIGrp,,tctl00$Body$updITyp,,tctl00$Body$updRpt,,tctl00$Body$updSrch,,tctl00$Body$updDoc,|0|childUpdatePanelIDs|||57|panelsToRefreshIDs||ctl00$Body$updRpt,,ctl00$Body$updSrch,,ctl00$Body$updDoc,|2|asyncPostBackTimeout||90|0|formAction|||39|scriptStartupBlock|ScriptContentNoTags|removeLastColumn('ctl00_Body_grvDocs');|208|scriptStartupBlock|ScriptContentNoTags|Sys.Application.add_init(function()
{ $create(Sys.UI._UpdateProgress,
{"associatedUpdatePanelId":"ctl00_Body_updRpt","displayAfter":0,"dynamicLayout":false},
null, null, $get("ctl00_Body_ctl07"));
Is there any way I can prevent this from being sent in response?
Extracted from stackoverflow:
The __VIEWSTATE field is also used to store control state, which is
not optional. Furthermore, the information contained in the view state
is used to validate the postback, if I'm not mistaken (and validation
is enabled, which is the default). So as long as you have the form
with runat="server", you'll have a viewstate field. However, you
should notice a much smaller field size if you disable all viewstate.
By the way, there are some tricks to remove the viewstate. Check the following post:
Override Render and strip ViewState out with a Regex.
Set the 'EnableViewState=false' on the UpdatePanel. This will disable the ViewState of all child controls contained within in. Or, if you need a more granular approach, you can disable the ViewState on a control by control basis too.
I am dynamically loading user controls to switch between views in my project. I am aware that I need to reload my user control on every postback. The odd thing is my viewstate for the control is maintained even though the control is gone? I confirm that the panel I loaded it into is empty and then I check the view state and my value is there.
What's stranger is that if I load a different control, it can see the viewstate from the previous control? I checked and my page cannot see viewstate from my dynamically loaded control and visa versa. This makes me think the user control is treated as its own page. The confusing part is why the second view I load can see values from the first and why the values are there even though I the control has disappeared?
I also find this section of the code to be useless. Why is it removing the control? The panel is always empty (the code is from Telerik):
string controlId = LatestLoadedControlName.Split('.')[0];
Control previousControl = pnlControlPlaceholder.FindControl(controlId);
if (!Object.Equals(previousControl, null))
{
this.pnlControlPlaceholder.Controls.Remove(previousControl);
}
I looked at several posts and most say that viewstate is lost on every postback, although this is not the case for me. Perhaps because I'm using update panels. Although if an intial request handles an event and then reloads the same control again, the viewstate is lost. It only seems to preserve the viewstate on the very next postback.
Can anyone explain this odd behavior of sharing viewstate between user controls or why it is there even though the control is lost?
Apparently you can read viewstate between pages in two scenarios... Cross page postback and when using Server.Transfer. I believe the cross page postback scenario would explain what I am seeing.
I have a Web User Control that I need to add to a page simply in order to add it to an HtmlForm so I can send an email with this User Control, however, I do not need this Control to appear on the page, I just need it to fill with data so I can send this email, and then be removed so it does not appear on the page.
Currently I have tried:
myControl c = new myControl();
c.InitializeAsUserControl(Page);
c.fillInfo(data);
//add to email form and send email
yet this adds the control to the current page on post back once the email has been sent and a confirmation message
I have also tried
myControl c = (myControl)Page.LoadControl("~/filename.ascx");
//send email
Page.Controls.Remove(c);
yet this also renders the control on the page and does not remove it. I have tried to add it to a panel and set Visible to false, but unfortunately this does not work either. If I simply create a new myControl() without rendering on page or calling LoadControl I get exceptions thrown when fillInfo is called when it tries to modify asp:labels in the User Control saying that the objects are null or not instantiated.
Which part of the page cycle are you loading and unloading the controls? To work properly it needs to be done in Page_Init. It's a common mistake to do it in Page_Load. If it is added anywhere else other than Page_Init it won't be added to the ViewState correctly and problems will ensue.
Rather than unload - I would add it to a Panel and set Visibility to false. Could be the reason that isn't working for you at the moment is that the control is being added at the wrong part of the page cycle and isn't being added to ViewState correctly.
Could that be your problem?
I suggest reading the entire TRULY UNDERSTANDING DYNAMIC CONTROLS series. To successfully use dynamic controls with postbacks, viewstate, bindings, and the other WebForms features, you really have to know the page and control lifecycles and their interactions inside out.
When you load and set ViewState depends on the cycle. ViewState is loaded between Page_Init and Page_Load, so the control has to be in Page_Init. However, any processing based on auto-loaded ViewState, needs to go in Page_Load. Where/when ViewState is enabled depending on the control hierarchy can also affect this. I suggest you read that guide above in depth if you really want it to work. Or, you'll have to post your entire control code and its use in a page for us to tell you which parts you are missing or have in the wrong part of the page lifecycle.
I've made dynamic controls work, but 99% of the time, unless the control is extremely trivial, it's easier to find a different solution than it is to make sure all the interactions work correctly with dynamic control creation.
In my ASP.NET page I have to dynamically choose and load a custom control, depending on the selected value in a dropdownlist.However I encountered the following problem:
When the parameters of the dynamically loaded control are changed, and then the selection in the dropdownlist is changed( thus forcing me to load a different dynamic control the next time the page reloads ), I end up with a "Cannot load ViewState" exception.I assume that this happens because the ViewState is trying to restore the parameters of the old control and it doesn't find it.
So , is there any way to stop the viewstate from attempting to restore the state of the non-existig control?
You should load the controls the exact same way initially and then alter then after LoadViewState or disable the viewstate on the dynamic controls you know will not be in sync with the page.
It sounds like the state of the drop down / added control is not being restored before you are restoring the view state. If you have the drop down defaulted to show control X, and the user changes it to show control Y, the page must add control Y to the control collection before view state is restored.
Had the same issue where a variable length list of controls was added, rearranged and/or modified by the user and is changable during each postback.
The answer is surprisingly simple.
When you create the dynamic control set "EnableViewState = False" before you add it to the pages control collection. Then no viewstate information is stored and regardless of how many dynamic controls are added or removed or re-ordered the viewstate for everything else will work correctly.
If your adding these dynamically you are normally setting all the properties anyways so it didn't actually create any work in my case which is very similar.
I've the same issue with grid control. I was binding dataviews dynamically and according to DarrenMB's solution I've just write EnableViewState = false; and problem solved.
Infragistics.Web.UI.DataSourceControls.DataView dvMesaj = new Infragistics.Web.UI.DataSourceControls.DataView();
whdsShowMessages.DataRelations.Clear();
whdsShowMessages.DataViews.Clear();
whgridShowMessages.Rows.Clear();
EnableViewState = false; //here is the solution..
whdsShowMessages.DataViews.Add(dvKisi);
whdsShowMessages.DataViews.Add(dvMesaj);