ASP.NET DataSource Control "does not have a naming container" exception
Asked Answered
T

4

5

I've been getting this exception in my code and wondered if anyone could help me out.

I have a Repeater Control bound to an ObjectDataSource, and the itemtemplate for the repeater contains a User Control (ASCX). This user control in turn contains several other controls, mainly a GridView that is associated with an ObjectDataSource.

On initial use of the controls in this setup, everything works great - data displays properly. However, when I change a filter option (dropdowns outside of the repeater), and then rebind the Repeater, I get the exception:

The ObjectDataSource control 'expDataSource' does not have a naming container. Ensure that the control is added to the page before calling DataBind." at System.Web.UI.WebControls.DataBoundControlHelper.FindControl(Control control, String controlID) ... ... at System.Web.UI.WebControls.ObjectDataSource.LoadCompleteEventHandler(Object sender, EventArgs e)

I'm not sure what the problem is - I've read in a few places that moving the datasource outside of the ASCX control might help - this does nothing. The objectdatasource appears to be properly structured, and as I said, it works the first time (only).

I noticed in the stack trace for the exception that this is occurring when ASP.NET is calling FindControl() after LoadComplete() occurs. If I step through my code, it appears as though all my code is finished executing before this happens, so it's all "system" code.

Why would ASP.NET not be able to find this datasource control in the LoadComplete Handler?

Thanks!

Other Notes:

  • This error occurs every other time. So the first time the data loads properly, then on second refresh fails with this error. Clicking "Load" again, it works (on the third time).

  • On the times that it fails, it looks like "Page_Load" is being called twice in the ASCX control. So the patterns are:

    1. Working Pattern:
  • Page_Load on Parent Page
  • Page_Load on ASCX
  • Data Loads fine

    1. Failing Pattern:
  • Page_Load on Parent Page
  • Page_Load on ASCX
  • Page_Load on ASCX
  • Exception

This is all happening from a call to "Repeater.DataBind()", but it behaves differently depending on if it has already been bound or not (evidently).

More Notes:

Real strange behavior. I removed the list of SelectParameters from the bottom of the ObjectDataSource, and all of a sudden, the page does not reject the ObjectDataSource as not having a NamingContainer. Of course, without these parameters, Databinding won't actually work...I can add them in the code, but why would it matter?

Tunable answered 16/11, 2009 at 15:44 Comment(17)
Sounds like your initial successful load is with a 'GET' request, and the failure occurs in a 'POST' - are you using an 'if (IsPostBack)' thing to load controls or data differently?Phase
No - both types of requests should follow the same flow. Hmmm...Tunable
I think the initial load is a POST as well actually, because they first select a few options from the filter controls (DropDowns) before clicking a "Load" button for the first load.Tunable
does it work if you turn view state off for the repeater?Phase
Yes - if I turn the ViewState off for the repeater, the error goes away. Problem is, I need ViewState to be on because of temporary controls I'm adding (at least without making some major changes to this). Why would turning ViewState off make the error go away?Tunable
View state gets used to reconstruct the repeater controls on post back - if you have itemcreated or itemdatabound event handlers, you could trace into them to see if it is failing on your data bind or on the reconstruction (called by internal code), and then to see why the error occurs - if you are just going to discard and rebuild the repeater, the view state is a waste - what do you do with the temporary controls?Phase
Ray - I don't discard the repeater each time. This repeater is within a WARP panel (AJAX panel), and the grids within the repeater contain buttons in their cells that make changes to the grid. For instance, there's an "Edit" button, that when clicked, changes the contents of a grid cell to a textbox instead of a label. When I turn off the ViewState, clicking that add button makes all the content of the repeater vanish (because it's not being retained in the ViewState to be rebuilt I assume). With the temporary controls, I store them in session and re-add. So those might not be using VS.Tunable
The other weird thing I noticed - loading the data in this way works every other time. So it works the first time, fails the second with that exception, and then works the third time, fails fourth. When stepping through the code, I also see a weird pattern with the Page_Load events of the containing page and the control. I'll detail above..Tunable
So you are doing an 'editable grid' kind-of-thing? Sorry to say I don't have much experience with that, or with the ObjectDataSource. It sounds like you have two different post back situations - one is an ajax post for editing and saving individual items in the grid, and the other is when the user changes the filter. In this second case, the original repeater data would be discarded - correct?Phase
Correct - in the second case, when a filter is changed, the whole repeater is discarded. The trouble comes because certain actions inside the repeater cause it to need to be rebuilt without the filters changing necessarily. So like there's a "Approve" button that means that the approved item needs to drop out of the repeater, because it no longer is Un-Approved. So I call "repeater.DataBind()" on that button click, and it all blows up with that error instead of rebuilding. Also, when I override the Page.OnLoadComplete method, on the working calls, repeater.Items is zero, and 1 on failTunable
Aha (I think) - don't call DataBind on the ajax calls (approve, edit, etc) - the repeater should rebuild itself - of course, since I have not used a repeater this way, I don't know if this will work...Phase
Yeah - the DataBind being called by the buttons that live within the Repeater is definitely what causes the issue, but I'm not sure how else to get the Repeater to reload itself. If I don't make the "Approve" button call DataBind(), for instance, then the AJAX panel just flashes and nothing is reloaded. I wonder if the issue has something to do with the fact that the button that is triggering the DataBind() lives within the repeater....Tunable
probably a dumb question, but are you setting the DataSource property every time before you call DataBind?Phase
Originally, I was only setting DataSourceID in the code the first time. The value stayed populated, but I went ahead and tried just setting it declaratively in the ASPX code, which threw the same error. What doesn't make sense is even if I disconnect the ObjectDataSource from all controls (it isn't the datasource for anything), this error still occurs. And, there are 3 other Objectdatasources within the control that this is not a problem for!Tunable
Man, this is freaking strange. If I delete the <SelectParameters> list from the bottom of the ObjectDataSource, then I no longer get this error just from having this ObjectDataSource live on the page. Of course, the actual databinding (which I turned off just to get things working) won't work without these Select parameters. Why in the world would taking the Select parameters off make it all of a sudden start getting a NamingContainer (in the eyes of ASP.NET)?Tunable
Sorry, Sam - I am out of ideas. This is one of the reasons I haven't used these asp.net features much - the internals are pretty mysterious and it can be hard to figure these problems out. I hope someone else chimes in for you. Good luck.Phase
Thanks Ray - you're definitely right - the internals can be a pain and are very shadowy. I think this would have been easier had I done it in MVC...Tunable
T
4

Found a strange solution, that I'll post and we can discuss to maybe figure out why this fixed it.

On my page, I had the following structure (paraphrasing the tags somewhat):

Page

DropDownFilter

Repeater

UserControl X

ObjectDataSource

ControlParameters Referencing DropDownFilter

End ObjectDataSource

End UserControl X

End Repeater

End Page

So as you can see, within the Repeater ItemTemplate was the user control, which in turn had the "guilty" ObjectDataSource with ControlParameters. These control parameters had the name of the DropDownList filter on the parent page referenced (so basically, if this control was added to any other page, it would of course fail if it couldn't find a control with the proper name).

So when I went through and changed all the ControlParameters to Parameters (removed the reference to that DropDownList control), now I no longer get the error.

All I can assume is that the fact that this datasource referenced a control on the parent page meant that it was having trouble getting added back to the page's control set on a DataBind(). You would have thought it would fail the first time if it was going to fail at all, so that's still a mystery.

Any thoughts?

Tunable answered 17/11, 2009 at 14:51 Comment(4)
Honestly... no clue. The fact it didn't happen with ViewState off is what made me think you are just doing one too many data bindings. The controls inside the repeater are recreated each time you bind, which is one reason why you'd get multiple Page_Loads. After a postback, the controls are recreated from ViewState. Then another (inappropriate) call to DataBind gives you the second Page_Load. I'm not too familiar with the ObjectDataSource control. This sort of issue is exactly why I like to do all my binding explicitly in code behind. :) No behind-the-scenes magic to account for!Esculent
Bryan - yeah, I tend to use a mix of built-in and behind the scenes controls, depending on what I'm doing. Everywhere else on the page, I'm doing my own binding in the code, but I'm using the ObjectDataSource for binding this particular GridView, because it handles so many of the editing/sorting/etc. with minimal effort. Usually I have pretty good luck with them, but of course this page is getting pretty complicated too. You're definitely right about the reasons for the multiple Page_Loads, the strange thing is why the second one would fail while the first one works.Tunable
2015 and I'm still doing Webforms... (a legacy application). Nevertheless: I think your assumption is correct. I encountered this issue while manually calling DataBind() on the parent control. Changing all ControlParameters to Parameters and filling in the value (DefaultValue) in the ItemDatabound event handler of the parent control solved the issue. Mysterious ways...Second
Had same issue. Changing ControlParameters that were pointing to control on the parent page to regular Parameters and setting the values manually in the code behind solved this issue.Dravidian
M
2

This is an exceptional error in ASP.NET DataControls. I had similar problem and lost few months behind this eccentric error, but finally got the solution. The reason is; To display items in ItemTemplate, we should use a server control in the LayoutTemplate to act as the placeholder for the ItemTemplate. For example, we could use a Table/Div control with an ID Property in Layout Template. At run time, this placeholder control will be replaced with the contents of the ItemTemplate and "naming container error" will be disappeared. Finally, if you are having an objectDataSource in ItemTemplate, make sure that you added somthing(like table/Div) with "Id" property in Layout Template.

Thanks, Sunil.

Metic answered 27/6, 2010 at 7:43 Comment(0)
E
1

Ray hit the nail on the head. You are definitely missing an "if(!IsPostBack)" somewhere. How are you adding the user control to the repeater? Is it dynamic? You say it's in the ItemTemplate, so probably not... But multiple calls to Page_Load imply multiple copies of the control.

Esculent answered 16/11, 2009 at 22:28 Comment(1)
Bryan - the control is actually declared in the ASPX itself - not added in the code. So I'm guessing the reason for the 2 PageLoads is because: 1. First Page_Load called as usual 2. DataBind called on Repeater from button event control 3. Repeater repopulates and re-adds controls, so Page_Load called again on control Regardless, I did find a strange solution to this, which I'll post some details about.Tunable
T
1

Use both DataBind. Example:

SqlDataSource1.DataBind();
ListView1.DataBind();
Tumulus answered 12/9, 2011 at 20:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.