What's the difference in behavior between adding a control to an ASPX page directly, loading a control programmatically & adding to a placeholder? - asp.net

Is there a difference in behavior between adding a control to the ASPX page directly and loading a control programmatically and adding to a placeholder?
The control inherits from System.Web.UI.WebControls.DataBoundControl.
The reason I ask is that I have a control that works when I add it to the ASPX page like so:
...
<blah:GoogleMap ID="GoogleMap1" runat="server" Width="640px" Height="600px" ... DataSourceID="_odsMarkers" DataAddressField="Address" DataTextField="Description">
</blah:GoogleMap>
...
But not when I use the following in a codebehind page:
GoogleMap map = (GoogleMap)this.LoadControl(typeof(GoogleMap), new object[] { });
//... set properties
this.placeholder1.Controls.Add(map); //add to placeholder
Anyone have any ideas why this might be the case?

The control tree ends up the same if you define in markup or add programmatically. However there is plenty of room for the control implementor to screw up along the way.
You can go look how ASP.NET compiles the aspx:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files
The timing when the control is added to the page might be an issue. The usual pattern is add the control in an overload of the CreateChildControls method. If the control needs to resolve viewstate you need to make sure this is called during init, e.g. by calling EnsureChildControls.
Adding to ninja's debbugging hint. Does it make any difference if you add a label the same way. Does it show up?

Is this a user control or server control?
If it's a user control they should be loaded by their path and not their type:
GoogleMap map = (GoogleMap)this.LoadControl("~/Controls/GoogleMap.ascx");
If it's server control then you can just new up an instance:
GoogleMap map = new GoogleMap();
after you have the instance and add it to the control tree (by inserting it into the PlaceHolder) it should perform the same as when it would have been declared in the markup.

If you are setting properties outside of the LoadControl call, why are you making that new empty object array instead of just using the overload that has one parameter?
Also, if you attach a debugger to it and step through, do you notice anything weird about the control before you do your Controls.Add() call? Is there an exception being thrown? if so, which one? if not, what does the markup in the browser look like for where the placeholder is?

"Works" is kind of ambiguous, but if you mean, event handlers are never executed, you need to load it in the page onload event.

If the control requires the use of viewstate you must ensure that it is added to the page BEFORE the Page_Load event, otherwise viewstate will not be populated and most likely events and other items will not function properly.

One important difference is that if you create a control dynamically, you will not get, by default, any values from skins set. You must manually call control.ApplyStyleSheetSkin(page): http://msdn.microsoft.com/en-us/library/system.web.ui.control.applystylesheetskin.aspx

Related

Failed to load viewstate. The control tree into which viewstate is being loaded

I am receiving the following error message after an HTTP POST on an ASP.NET form hosted inside a UserControl:
Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.
Here's additional info:
I'm running .NET 4.5 RC
It's an Umbraco 4.7-based website
On my local dev machine the form works perfectly
This error only occurs on the staging server which has .NET 4.5 (only), MSSQL 2012 Express, IIS 7.5, Windows 7 (I know, it's not a real server yet, one day maybe...)
The server is not part of a web farm (or garden, tho that should be irrevelant)
The user control does render controls dynamically
I have applied all the latest service packs.
I have run out of ideas now! I have even restarted it and also performed a richual over the server involving a song and a special dance to no avail.
What is important when you are adding controls dynamically is on which event you are adding them.
If you added controls on events that occur after load, they will be part of the viewstate you send to the client.
You will have to add those controls again before LoadViewState is called.
If you run into cases where the decision of which controls to add is itself stored in the ViewState or the value of a control, then remember even before the ViewState is loaded, this data is available in Request.Params
Refer the asp.net page life cycle
I just added EnableViewState="false" to my page placeholder and its gone. Hope it works for u as well.
This Error Mainly Occurs during View state Change: From One Template To other Template like in case of Item Template, Edit Item Template, in Controls like Form View, List Views, Detail View, Grid View in ASP .net (all frameworks);
While Changing from control states say Item Template ---> Edit Template
the followings were going to alter
1) Controls will change (its ID & states)
2) Its Positions will change.
While Transformation of view if any post back occurs you will get Error as
Failed to load viewstate. The control tree into which viewstate is
being loaded....
if you are using separate control for data-binding like (button,link_button_Image_button events) you will get this error reported !
To avoid this error >>> Once state changes from one template to other within method you call data source binding ( Don't call during click or any post backing events ).
OK, so the answer is literally: "Set up a new server with all the same software as the last one and try again" and it works now.
I add "name" attribute with the same value as id, then this problem is gone.
<input type="button" id="extractBomInfoBtn" name="extractBomInfoBtn" value="Extract" class="button textonly" />
I had the same issue. This issue was at client end but it didn't occur in my local system.
After hours of googling, i had written EnableViewState="false" to my table tag in aspx page which has all the dynamic controls and then i removed all the viewstate variables and instead i created some hidden textboxes in the aspx page and accepted DB values into them in code behind and used them throughout my code. It then solved my problem.
But still, i couldn't figure out what was exactly the problem.
In my case I was manipulating the .Text property of a asp:Literal on page load which was causing the issue. In all other cases this never caused me a viewstate error but in this particular case I was changing the .Text value to an html element.
The following caused the error:
<asp:Literal ID="SvgIcon" runat="server" />
SvgIcon.Text = "<svg version=\"1.1\" id=\"Layer_1\" bla bla />"
I was able to resolve the error by adding EnableViewState="false" explicitly to the control:
<asp:Literal ID="SvgIcon" runat="server" EnableViewState="false" />
Check if you have the binding method of the control directly in your page load event. This can cause this problem.
You can add new PlaceHolder per UserControls
OR
You can set enableviewstate=false on the control , if you dont need viewstate
In my case I had a grid view with (OnPageIndexChanging) event
and when I click on a page nothing will happen until I click it twice!
I was refreshing the data source before setting new page index.
This is what I was doing wrong
grd.DataSource = data;
grd.DataBind();
grd.PageIndex = e.NewPageIndex;
This is the right way
grd.PageIndex = e.NewPageIndex;
grd.DataSource = data;
grd.DataBind();
This can happen if you override SaveViewState in your control but don't override LoadViewState.
So I actually ended up discovering that the list of entities I was binding to was not in the same order as the controls in ViewState! I'm still working thru a cleaner solution, but my code is working with ViewStateEnabled = true by having the method which reconstructs my dynamic controls (called from Page_Load) do it differently if !IsPostBack.
Ultimately, I will probably need to fix my sorting algorithm for my nested dynamic controls, but suffice it to say: if you are using the same pattern as I am, of using a List to generate/bind to dynamic controls, and that order is fluid or changing, try comparing Request.Params to find the keys that are relevant to your control hierarchy, and see if they match the order of your List. That solved my issue. Kudos to #nunespascal!
In short, I am dynamically generating all but one tab in an AjaxToolkit tab control, and then populating that with a couple layers deep of placeholders and regular controls (textboxes, dropdownlists, etc), so that's why it's complicated to get the order of everything correct.
Although this is very old question, I had visited this as I got the similar issue. But my issue was generated just because I have added a javascript code in Master page in head tag. That javascript code is reading a value of Session["KeyName"] ,
Code is like below -
$(document).ready(function () {
var allowOpenInNewTab = false;
allowOpenInNewTab = '<%# Convert.ToString(Session["AllowOpenInNewTab"]).ToLower() %>' == 'true';
if (!allowOpenInNewTab && window.sessionStorage.tabId != '1') {
alert("This page is not allowed to be open in another tab, sorry we can not load the page!!");
}
});
When I remove above code then everything was running smoothly but if I keep adding this part of code, it was giving this error of
Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate...
Finally I found the solution like if I move my javascript code from head to just before the end of the body tag.
So solution that worked for me was moving javascript code (which is reading Session value from Server tags) to just before end of body tag.

What is the correct ASP.NET Control event/method in which to add nested controls?

What is the correct event/method in the ASP.NET life cycle to dynamically add Child Controls ?
My objective is to ensure that all the input controls on a User Control have the correct associated Validator and Label controls, based on configuration from an external file.
It seems like the correct place should be either OnInit(EventArgs e) or CreateChildControls(). Both of them are behaving a little bit unexpected, and rather than try to debug each of them, I figured I'd first ask you guys which one (or other) to use.
Its OnInit, and you need to do it on first load and on post back.
Since this is a Web User Control (ASCX) create the dynamic controls during OnInit. By creating them during OnInit they will be created on the first page load and on every postback.
The CreateChildControls method is typically used for rendering in custom server controls.

Dynamic adding controls during OnLoad or OnInit?

I want to add more controls to page based on some specific conditions. Those controls don't need any ViewState or binding data, it is as simple as a static link.
I wonder where I could write the code: inside OnLoad or OnInit method? and why? If I place it inside OnLoad, should I add following line: if (IsPostBack) return; before any initialization code?
You can add controls in either the OnInit method or OnLoad, whether they need view state or not. (The reason why is because as soon as you add a control to the Page the control loads its view state, even if you add it after the LoadViewState stage...)
should I add following line: if (IsPostBack) return; before any initialization code?
No. It is imperative that your dynamically added controls are added to the control hierarchy on every page load, not just the initial one.
If you are going to work with dynamically-added Web controls, I strongly suggest you read these two articles:
Dynamic Controls in ASP.NET (This is actually three articles, this being the first in a series.)
Creating Dynamic Data Entry User Interfaces
For a working, end-to-end example of dynamically loading controls based on some external conditions (such as configuration in a database), see Creating a Dynamic Data-Driven User Interface.
Happy Programming!
I would suggest just adding the controls to the page statically and toggling their visibility to "True" when the conditions are met. They won't render anything to the page when they're invisible, and this will save you a lot of headaches, especially since it sounds like you're fairly new to dynamic controls.
I'm not sure I fully understand, but I'd personally put an asp:Literal on the page (or several if you need them in different places) and then create the HTML you need in the OnLoad event.
If you do that, then the html you put into that literal will be saved in viewstate, and therefor you won't have redo it on postback.
http://chetanwarade.wordpress.com/2010/08/21/asp-net-add-dynamic-control-and-retrieve-dynamic-control-value-2/
Here is code that demonstrate how to add dynamic control and retrieve dynamic control value.

How do I temporarily convert an ASP.NET Ajax form to not use partial page updates?

I need the ability to temporarily turn off the partial page update behavior for an ASP.NET Ajax / UpdatePanel based page. (The reason is to circumvent the issue where IE blocks "automatic file downloads" for downloads generated as a result of this postback, but I don't want to distract from my original question)
I looked at the client side javascript libraries hoping to find a switch somewhere. I think a solution might involve using javascript to override the 'onclick' event handler for the control that acts as the trigger, and then calling "submit" on the form itself..
Also, using the EnablePartialRendering property on the server-side ScriptManager control won't work because that is done when the page is being built. I need to be able to do this as a result of switching a drop down list box.
Any ideas?
Cheers!
/ Sean
Well, after much trial and error, I found two approaches that seemed to work:
Use Javascript to manually submit the top level form associated with the page. This usually has the ID of "form1".
Create a button that is outside of any UpdatePanels and use Javascript to click the button.
I wound up using the second approach, since it allowed me to handle the event with a specific routine without the need to guess that my postback came from a Javascript call.
This is an example of the code that performed the postback:
...
if (isDownload) {
document.getElementById('FullPostbackSubmitter').click();
return;
}
...
Hope this helps someone else!
You can set the EnablePartialRendering property of your ScriptManager to false.

Dynamically added controls in Asp.Net

I'm trying to wrap my head around asp.net. I have a background as a long time php developer, but I'm now facing the task of learning asp.net and I'm having some trouble with it. It might very well be because I'm trying to force the framework into something it is not intended for - so I'd like to learn how to do it "the right way". :-)
My problem is how to add controls to a page programmatically at runtime. As far as I can figure out you need to create the controls at page_init as they otherwise disappears at the next PostBack. But many times I'm facing the problem that I don't know which controls to add in page_init as it is dependent on values from at previous PostBack.
A simple scenario could be a form with a dropdown control added in the designer. The dropdown is set to AutoPostBack. When the PostBack occur I need to render one or more controls denepending on the selected value from the dropdown control and preferably have those controls act as if they had been added by the design (as in "when posted back, behave "properly").
Am I going down the wrong path here?
I agree with the other points made here "If you can get out of creating controls dynamically, then do so..." (by #Jesper Blad Jenson aka) but here is a trick I worked out with dynamically created controls in the past.
The problem becomes chicken and the egg. You need your ViewState to create the control tree and you need your control tree created to get at your ViewState. Well, that's almost correct. There is a way to get at your ViewState values just before the rest of the tree is populated. That is by overriding LoadViewState(...) and SaveViewState(...).
In SaveViewState store the control you wish to create:
protected override object SaveViewState()
{
object[] myState = new object[2];
myState[0] = base.SaveViewState();
myState[1] = controlPickerDropDown.SelectedValue;
return myState
}
When the framework calls your "LoadViewState" override you'll get back the exact object you returned from "SaveViewState":
protected override void LoadViewState(object savedState)
{
object[] myState = (object[])savedState;
// Here is the trick, use the value you saved here to create your control tree.
CreateControlBasedOnDropDownValue(myState[1]);
// Call the base method to ensure everything works correctly.
base.LoadViewState(myState[0]);
}
I've used this successfully to create ASP.Net pages where a DataSet was serialised to the ViewState to store changes to an entire grid of data allowing the user to make multiple edits with PostBacks and finally commit all their changes in a single "Save" operation.
You must add your control inside OnInit event and viewstate will be preserved. Don't use if(ispostback), because controls must be added every time, event in postback!
(De)Serialization of viewstate happens after OnInit and before OnLoad, so your viewstate persistence provider will see dynamically added controls if they are added in OnInit.
But in scenario you're describing, probably multiview or simple hide/show (visible property) will be better solution.
It's because in OnInit event, when you must read dropdown and add new controls, viewstate isn't read (deserialized) yet and you don't know what did user choose! (you can do request.form(), but that feels kinda wrong)
After having wrestled with this problem for at while I have come up with these groundrules which seems to work, but YMMV.
Use declarative controls whenever possible
Use databinding where possible
Understand how ViewState works
The Visibilty property can go a long way
If you must use add controls in an event handler use Aydsman's tip and recreate the controls in an overridden LoadViewState.
TRULY Understanding ViewState is a must-read.
Understanding Dynamic Controls By Example shows some techniques on how to use databinding instead of dynamic controls.
TRULY Understanding Dynamic Controls also clarifies techniques which can be used to avoid dynamic controls.
Hope this helps others with same problems.
If you truly need to use dynamic controls, the following should work:
In OnInit, recreate the exact same control hierarchy that was on the page when the previous request was fulfilled. (If this isn't the initial request, of course)
After OnInit, the framework will load the viewstate from the previous request and all your controls should be in a stable state now.
In OnLoad, remove the controls that are not required and add the necessary ones. You will also have to somehow save the current control tree at this point, to be used in the first step during the following request. You could use a session variable that dictates how the dynamic control tree was created. I even stored the whole Controls collection in the session once (put aside your pitchforks, it was just for a demo).
Re-adding the "stale" controls that you will not need and will be removed at OnLoad anyway seems a bit quirky, but Asp.Net was not really designed with dynamic control creation in mind. If the exact same control hierarchy is not preserved during viewstate loading, all kinds of hard-to find bugs begin lurking in the page, because states of older controls are loaded into newly added ones.
Read up on Asp.Net page life cycle and especially on how the viewstate works and it will become clear.
Edit: This is a very good article about how viewstate behaves and what you should consider while dealing with dynamic controls: <Link>
Well. If you can get out of creating controls dynamicly, then do so - otherwise, what i whould do is to use Page_Load instead of Page_Init, but instead of placing stuff inside the If Not IsPostBack, then set i just directly in the method.
Ah, that's the problem with the leaky abstraction of ASP.NET web forms.
Maybe you'll be interested to look at ASP.NET MVC, which was used for the creation of this stackoverflow.com web site? That should be an easier fit for you, coming from a PHP (thus, pedal-to-the-metal when it comes to HTML and Javascript) background.
I think the answer here is in the MultiView control, so that for example the dropdown switches between different views in the multi-view.
You can probably even data-bind the current view property of the multiview to the value of the dropdown!
The only correct answer was given by Aydsman. LoadViewState is the only place to add dynamic controls where their viewstate values will be restored when recreated and you can access the viewstate in order to determine which controls to add.
I ran across this in the book "Pro ASP.NET 3.5 in C# 2008" under the section Dynamic Control Creation:
If you need to re-create a control multiple times, you should perform the control creation in the Page.Load event handler. This has the additional benefit of allowing you to use view state with your dynamic control. Even though view state is normally restored before the Page.Load event, if you create a control in the handler for the Page.Load event, ASP.NET will apply any view state information that it has after the Page.Load event handler ends. This process is automatic.
I have not tested this, but you might look into it.

Resources