FindControl won't find my dynamically added UserControl - asp.net

I'm working on a project where the page load certain controls depending on the index available. The loading occurs in the page load where the method PopulateSearchField is called.
Within this method, all the UserControl are added on the page using : Page.LoadControl("path");
The page load and all the required controls are on the page. My problem is when the user click on the Search button the event is triggered and a query is built based on the user input int those controls. Unfortunately, the method isn't able to produce a proper query as it is unable to find any of the controls on the page.
With a temporary ControlCollection variable, I've been able to see that the number of controls on my page is 3 when it should be something from 4 to 10. Those 3 controls in the collection are the static label and buttons on the page.
I don't know if something is wrong with the code or if it's a page cycle problem as this solution used to work on framework 1.1. Yeah, I know this isn't the best thing to do so, but they did it this way and I gotta make it work.
I'm not sure if it is the migration that has caused the problem or not.
Thanks a lot, David!

When you click the button, the controls are no longer available server side when your click handler is being processed. The page, server side, has no knowledge of the controls you created dynamically since there are no server side controls for the posted values to map to. If you want to find the values, you need to inspect the posted control data and not rely on the server side asp.net control heirarchy.
You could also write all the data you require to a hidden field via javascript and then read the hidden data server side since it will will be posted.
The following is occuring:
Creating controls dynamically
Posting controls data on click
ASP.NET maps the data to the existing controls it knows about.
Your controls are not found so the data is no mapped to anything.
You need to add your controls before the mapping occurs (in PreInit). Check out the Page Lifecycle and you will see how it ties all the controls and data together.

Are you re-adding the controls to the new page when the user clicks search?
Remember... every time the user hits your server for that page... a new Page object is created. If you're dynamically adding controls, you have to do it every time the page loads.
Additionally, since you seem to want to get values out of the controls, you're going to have to make sure that the controls are created with the exact same ID property every time, and created before viewstate is loaded, if you want them to retain their values.

Related

What are the main differences of defining a control statically or creating it dynamically on page load?

I am working on a project which creates controls dynamically for a form in the page_load event, loads in their current values from the database and saves their values (using FindControl) when the user clicks the continue button.
When I added a control statically in the .aspx page and followed their same procedure of loading the value in the page load and saving it on the button press I found that the value would not save correctly. It seems that it wouldn't save because the click event fires after the page_load, so the page_load of the post back reverted the value and the user entered value was not saved.
The strange thing is that by changing the control to be dynamically created just as all the other controls on the page and keeping the loading and saving the same it now works. Even though the page load still creates the control with the old database value.
It seems like a very fundamental asp .net feature here but i'm just unclear as to what is going on. I suspect it is to do with the timing of creation and maybe when the view state kicks in.
Static page controls are created just like dynamic page controls. The difference might be coming in your Page_Load. Whenever you postback all the controls are created afresh which means they are created with their initial values. This happens because after creating the controls asp.net throws away the controls/objects.
So, when the request comes, the first thing that asp.net does it to recreate the controls by looking at their definitions (in the designer files). On each postback they are created and initialized again losing their state in the process.
But after creating the controls Asp.Net loads any viewstate that is sent along with the request which makes people think that the state is always saved at the server.
What might be happening is that either the viewstate is not enabled for your control (in case they are created in designer), in which case you may try using EnableViewState property to true of the control.
Or, when you're doing a Page_Load, you're forcefully re-initializing everything. And in process losing all the control data. If you could post the logic of Page_Load, it might get clarified.
Make sure that:
you are not setting the value again for the static control in Page_Load. The dynamic control are probably getting around it by grabbing the ViewState and form values at a different stage in the lifecycle.
The dynamic controls are added After the static control. Or at least they are added in a different container. Placement in the control's collection can affect the ViewState, although it doesn't look like your scenario / since what you mention seems to be more about the values in the current post.
The save is happening After the Page_Load in response to the corresponding event.
I've run into similar problems in the past (quite a few times actually), but what helped me the most is understanding the ASP.NET Page Lifecycle.
Microsoft has an article on it which describes it pretty well, but this post by Solomon Shaffer really cleared up everything.
I suggest reading them both and coming back with additional questions regarding to a particular state, when to load/save data etc..
Hope this helps.
Marko
Note that you may want to use Page.IsPostBack property to avoid reinitializing values on button clicks and other events.
private void Page_Load()
{
if (!this.IsPostBack)
{
// Assign values to the controls.
}
}

dynamically load user controls using jquery ajax

I've read several articles on this issue, and technically speaking, all they end up doing is taking html code from a user control and injecting it into the containing page. I want a true user control to be loaded on to the page, so that on postback, I still have access to that loaded user control and I can validate fields on it on server side, etc. etc. What I mean to say is that once the user control has been loaded onto the page using ajax, it should there after act like it was originally created as part of page life cycle when the page was first loaded. Does that make sense? Any ideas on how to do this? UpdatePanel may be a solution, but I'd rather not use that.
Update panel is the solution since you need it to update the page's ViewState so that the newly added usercontrol needs to be part of the page lifecycle. Also, when the page does post back, you need to remember that it was added and re-add it so that the control structure gets re-created properly.
When you dynamically create user controls, you have to make sure to bind to the elements. Look into http://docs.jquery.com/Events/live

Multiple controls with the same ID 'add0' were found. FindControl requires that controls have unique IDs

Previously Called: How to deal with dynamically created controls under load in aspx
in response to a question below: the information required to determine which controls to restore is contained in a dedicated viewstate object.
I am dynamically creating controls in the codebehind page - these controls are all hooked up to click handlers so when a postback occurs I must re-create the previous set of controls, then clear the controls down and generate the new set of controls based on the previous click.
This is coded and working correctly under normal circumstances esentially as follows:
in Page_Load
if not postback generate default buttons
else if postback re-generate buttons that were shown on last page
in click_handler
Clear the dynamically generated buttons created in the Page_Load
generate new buttons based on the specific click being handled
however when the server comes under load we start getting problems:
With 5 users per second we start getting the exception:
Multiple controls with the same ID 'add0' were found. FindControl requires that controls have unique IDs.
With 100 users per second we start getting the exception:
The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases.
Once this occurs all subsequent requests get the same error and IIS has to be re-started.
What could be causeing this and how can I avoid it? Do html requests possibly overwrite and interfere with each other when under load? do objects somehow hand around after a page unload in a manner that would allow the next page load to trip over them?
How are you storing information about the controls you need to restore? If you are using ViewState or ControlState, then I don't see how load could affect things. That's how any of the composite controls do things.
I will say that I saw your second error while using the Infragistics UltraWebGrid, and never was able to track it down. From the call stack, it appeared that EnsureChildControls was being called during the Load phase (or maybe LoadViewState).
A private static variable was being used to store a dictionary of names and table cells so that table cells would not get re-created during the page lifecycle.
The key point is that it was marked static - it should have been an instance variable - the end result being that under load when requests started backing up then multpile requests were sharing this static dictionary.
exactly what happened i'm not 100% sure - but under medium loads FindControl would find multiple controls of the same name, under very high loads it seems one request would try to modify a control (probably add to it) while it was in an invalid state from the other request.
End result - if you dont really know what your doing - prefer instance variable sto static variables.
Everything you have written seems to be correct and doable. Most likely this is an issue with your control generation code. Perhaps if you post some of that we can better find a solution.

ASP.NET Controls and Update Panels

I am creating a series of client side component controls on the fly that are nested inside a update panel. The first time I create the controls, everything works as desired, however, when i trigger an update on the update panel and it does a partial postback the controls come back with several javascript errors describing how the control is already registered on the page.
I get a series of errors that say something about like:
"Error: Sys.InvalidOperationException: Two components with the same id "master_ctl40_CCB_PALETTES" can't be added to the application"
Any ideas anyone?
Try these tricks:
On Page_Load put uxFailedControl.ID = DateTime.Now.ToString(); It will ensure your control has unique ID every time page reloads (fully or partially), so theoretically you shouldn't see anymore "same id" errors.
If you display your control in Modal Popup: Every time you hide the popup from the server, remove the control from it's container (Panel, Page, Control, etc.) Use uxModalPopupPanel.Controls.Clear(); or uxModalPopupPanel.Remove(uxFailedControl);
When you are done with debugging set ScriptMode property of your ScriptManager to "Release". It will prevent internal AJAX exceptions to be bubbled up to the browser.
In which event are you adding the components to the update panel? I.e. have you placed them inside the page load event without a postback check or have you placed them inside the update panel load event? etc...
Looks like your client object is being created more than once.
If you want your client side controls to be replaced when the update panel they're in refreshes, they should inherit from Sys.UI.Control, which takes takes an element in its constructor. When that element is replaced by the update panel, the client object will be disposed and then re-created. If you're currently using a ScriptComponentDescriptor on the server side to define the client control instance, you'll want to switch to a ScriptControlDescriptor.
By the sounds of it, your client objects just inherit from Sys.Component, which will hang around until they're manually disposed, which is why you're getting an error about having more than one component with the same ID.
I would advise against using a new ID every post back - this will just keep creating new client objects without ever cleaning up the old ones.

How to retrieve data from dynamically added textboxes?

Im adding textboxes (not a fixed number of textboxes) dynamically to a form on ASP.NET page, how do i read back data from these textboxes?
Assuming you're wanting to access the controls on the postback you'd probably re-create the dynamic controls exactly as they were created on the initial load, then use the page's FindControls method to find the controls. It would probably help to create the textboxes with IDs like Textbox1, Textbox2, etc.
Look at Request.Params and extract them from there. You will, of course, have to give them ids to be able to tell them apart.
From all the ASP.NET apps I've worked with, .NET likes to use the following algorithm when generating the Id for server controls:
ctl00$cphBody$[ControlID]
Try using this algorithm when accessing your data from the dynamically generated textboxes.
When you add them you should be giving them names/ids, and you can use those to reference them.
If not, walk your DOM in javascript to find them inside the form you made - they'll be in the same order you inserted them.
Lastly, they're all available as post/get inputs to your page, so you should be able to look at them all as long as you assigned them different names.
-Adam
When creating textboxes dynamically (presumably using JavaScript, but same goes for ASP.NET controls) give them names in a specific pattern. The one you will be able to recognize later.
On server-side, in any event handler occurring after Page_Init you can iterate through Request.Form collection.
Do not be tempted to use Request.Param because it can be used to apply cross-site request forgery on your application (an attacker could lure user into issuing a GET request which your application would interpret the same as it would interpret a POST one, which is usually not a good thing).
If you are adding dynamic ASP.NET controls (in Page_Render for example) you can also reconstruct controls and use their properties.
You can use FindControl and pass the textbox ID to get an instance of the textbox when post back. The Text property contains the data, given that we are at page load stage or later in the cycle.
When adding dynamic controls, override the CreateChildControls method and add the dynamic controls to control hierarchy at this stage of the cycle.
Remember that in ASP.Net, every postback is a new instance of your class. If you created these controls during a previous postback or on the first view then they were garbage collected with the rest of that previous instance. So to use the controls in this new instance, you need to create them again. If you need the state information loaded for those controls (including any value entered by the user), you also need to create before the viewstate is loaded, meaning you do it during the Init event, rather than the load event.
To create dynamic controls, I would usually use a ASP.NET PlaceHolder Control and add the dynamic controls to this container.
I would give each dynamic control an ID.
You can then subsequently use FindControl on the PlaceHolder to access the dynamic controls.
I say "dynamic controls" to mean controls you add at run-time

Resources