Dynamic Control loading at wrong time? - asp.net

This one is a little... odd. Basically I have a form I'm building using ASP.NET Dynamic Data, which is going to utilize several custom field templates.
I've just added another field to the FormView, with it's own custom template, and the form is loading that control twice for no apparent reason. Worse yet, the first time it loads the template, the Row is not ready yet and I get the error message:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control
I'm accessing the Row variable in a LinqDataSource OnSelected event in order to get the child object...
Now for the wierd part: If I reorder the fields a little, the one causing the problem no longer gets loaded twice.
Any thoughts?
EDIT: I've noticed that Page_Load gets called on the first load (when Row throws an exception if you try to use it) but does NOT get called the second time around. If that helps any...
Right now managing it by just catching and ignoring the exception, but still a little worried that things will break if I don't find the real cause.
EDIT 2: I've traced the problem to using FindControl recursively to find other controls on the page. Apparently FindControl can cause the page lifecycle events (at least up to page_load) to fire... and this occurs before that page "should" be loading so it's dynamic data "stuff" isn't ready yet.

You aren't referring to something in Page_Load that is set in OnSelected, are you? Something like your row object. OnSelected is a postback event and occurs after Page_Load. It's the only thing I can think of that might cause your exception when the row is not ready.

Start commenting things out in your code behind until either everything is commented or your control no longer loads twice.
If it is still doing it, start unhooking things in the control itself. Eventually, you'll get to the actual issue.

Related

Force the ASP.NET page lifecycle to go forward

Ok, so I am working on a custom framework above the .NET framework, and some instructions are not written / called at the good places.
For example, a postback is done on the same page. Then, a Response.redirect occurs right within the page_load; but at this point, the new values of the controls of the page are not yet handled, so they get lost...
Therefore, I wanted to know whether it was possible to force the pagelife_cycle to go forward before the call to response.redirect, so that I can get the right values.
I can't just make that call in another function, because the page I am working on is called by many web applications (about 1-2k), and it would completely change their behaviour, which is not acceptable!
Is that even possible?
See a bit the second image and the Load PostBack Data section. Before the Load event of the page is raised, a textbox is already initialized. You can catch the value by overriding OnPreLoad or by adding a handler at PreLoad event.

RegisterExpandoAttribute - Throwing Error

Recently, I discovered that using: someControl.Attributes.Add("customAttr", "customVal") is not compatible with all web browsers. The recommended registration for custom attributes is:
Page.ClientScript.RegisterExpandoAttribute(someControl.ClientID, "customAttr", "customVal")
Okay, here's the problem. I am using a ListView to generate a custom control. In certain scenarios, the ListView must be refreshed/recreated. When this happens, and a ListView item attempts the register (in this case, re-register) the expando attribute, the page throws the following error:
An entry with the same key already exists.
Obviously RegisterExpandoAttribute() does not behave like the Page.Cache object where if a key already exists, the current value is overwritten. I can easily hack my way past this problem but I wonder if there is a more elegant solution to this. For example, there is no method like: Page.ClientScript.IsExpandoAttributeRegistered(...)
Any ideas?
If you're creating a custom control, try doing the RegisterExpandoAttribute call during the control PreRender. I was having issues with the attribute still being registered if the control had been removed and doing that fixed my issue. I would imagine that if you're calling RegisterExpandoAttribute in the PreRender for the control then it shouldn't be called more than once per page load.

ScriptControl inside UpdatePanel

I have a ScriptControl (requires ScriptManager) with JavaScript to handle client-side interactions and ICallbackEventHandler to communicate back and forth. Everything works perfectly with one or multiple instances of the control on a page. I placed the control inside a GridView with sorting and it still works. However, I place the GridView in an UpdatePanel and now whenever I sort I get the following error for each instance:
Sys.InvalidOperationException: Two components with the same id 'GridView_ctl02_MyControl' can't be added to the application.
Can someone point me in the right direction on how to solve this? I am assuming ScriptManager is not disposing of the old Sys.UI.Control objects before trying to $create() the new ones with the same ID. I thought the UpdatePanel/ScriptManager combination would automatically take care of disposing objects that would be replaced?
Edit: This page appears to support what I thought: http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.registerdispose.aspx
Use the RegisterDispose method to
register dispose scripts for controls
that are inside an UpdatePanel
control. During asynchronous
postbacks, UpdatePanel controls can be
updated, deleted, or created. When a
panel is updated or deleted, any
dispose scripts that are registered
for controls that are inside the
UpdatePanel are called. In typical
page development scenarios, you do not
have to call the RegisterDispose
method.
Just to double check I placed an alert("dispose " + this.element.id) inside my JavaScript dispose() function. Every single instance alerts dispose GridView_ctl02_MyControl, but afterwards I get the error that two components can't have the same name GridView_ctl02_MyControl. I'm at a loss...
When the page unloads, my component's dispose() method is called and Sys.Application.removeComponent() is also called. When the UpdatePanel reloads, only dispose() method is called. For now I have solved this by putting Sys.Application.removeComponent(this); inside the dispose(). I didn't find a shortcut such as $remove (similar to $create), implying you aren't expected to need this often.
This seems logical in that you can keep a component loaded even after its related DOM elements (if any) have been replaced by the UpdatePanel. This way you have more control over the component's life. I can't imagine a use case, but I'm sure you could come up with one.
If I am way off and there is a better approach, please let me know!

Problem with asp.net C# focus, page_load

I'm really new to asp.net and have a couple of issues I'm trying to get fixed. I have some programming experience, but it is not asp.net. However, I've been able to follow the code enough to make other changes in the code to fix other issues.
The first is this:
I'm working with a form that has a calculate amount method that gets called when the user inputs a value in an amount text box. The same method gets called when the next control, number of payments, has a value.
So in the two controls:
onTextChanged="ctrlName_textChanged"
Then in the code behind, the textchanged method does:
calculateAmount();
The problem is after the amount is calculated and returns, the focus seems to get reset and the user has to tab all the way back through the form to the place they were.
The textboxes in question are in a panel that starts out hidden and is made visible conditionally.
My apologies if I have not used the proper .net terminology.
It looks like the same issue may be causing my second problem. When the user types in an amount and then tabs and quickly adds the number of payments, you can see the amount get calculated correctly and very shortly displays the proper total in the total amount text box. However, even though it shows for that short time, the tab order again gets reset as well as the total amount value.
I've looked at different methods to try and fix the focus issue.
In the textchanged method, I tried using something like:
Session["myval"] = "someval";
Then tried to check against that in Page_Load with something like:
if(Session["myval"] != null) {
this.NextControl_Name.Focus();
}
but it didn't ever work correctly.
I also tried to set a cookie in that same textchanged method using something like this:
Response.Cookies["myval"].Value = "somevalue";
Then tried to check that in Page_Load using something like the previous if block above but using Request.Cookies["myval"] as the source.
Is there a good reference with some really clear code samples I can look at for this type of implementation?
Thank you in advance,
C.
Sounds like you have a postback problem...
Remember that the web is stateless. This means that when you have a web page rendered out in .NET and you attach an event that executes serverside code... it does an HTTP POST back to the server which is effectively a new page request. The Page_Load method will fire again as well as your bound event. So your onTextChanged event is firing a new request back to the server. This is why you see the focus reset and why when you tab quickly, the value seems to disappear magically.
You can do one of several things, you can implement the UpdatePanel in the AjaxControlToolkit
http://www.asp.net/ajax/ajaxcontroltoolkit/samples/
you can use PageMethods and do your validation with javascript and jQuery (or other js library)
see page method info http://www.geekzilla.co.uk/View30F417D1-8E5B-4C03-99EB-379F167F26B6.htm
Hope this helps

Reasons why viewstate validation fails (but only sometimes)

The following message appears in our log:
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.
Well, that's pretty clear, and alot has been written about this subject. However, I cannot reproduce this behavior, and I only find a couple thousand errors per day in the logs; so it's probably isn't that obvious.
The page in question has an UpdatePanel and loads one of three usercontrols depending on the querystring.
Is there any known issue with some clients, or any other possible explanation?
One possible Issue could be, that
you load Controls dynamically
you do not give them explicit an ID
the order in recreation of these control is different (GET vs. POST)
I had such an issue once. Also Repeater are good candidates for such a behaviour because each Item is an INamingContainer. If the content of the Repeater changes during Postback you could get that error.
I've seen this behaviour in cases where update panels are on the page and a value somewhere outside of this is changed but never propagated to the client.
The solution is to make sure that any value that gets changed gets updated client side. Thus when the postback occurs all the data matches what is supposed to be there server side.
If you have such data you can put it into an update panel as well.
Set UpdateMode="Conditional" on it and in your codebehind you can just call the update panels .update method when you need to update it.

Resources