Update command not working in Dynamic Data Details view - asp.net

I have just create a very basic Dynamic Data web application using Entity Framework, and when I click the edit command from the GridView, to open a Details view, edit some fields, and click the Update link, nothing happens.
My question is what could cause this update to do nothing and are there any tips for diagnosing it?
MORE INFO It seems the EntityDataSource 'hides' exceptions. I have found more than one reason for the update or insert operation not completing, but I had to use a SQL trace and trap the command being sent. Running that command manually gives a quick and visible SQL error. Why this doesn't find its way to my UI is a mystery.

In general, anytime you are debugging or developing a Dynamic Data website, one should goto the Site.master file and set the ScriptManager's attribute EnablePartialRendering to false:
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="false"/>
This will make exceptions more apparent that otherwise seem to be swept under the rug because of the use of Update Panels that wrap around the DetailsView, FormViews and GridViews on the List/Edit/Insert/Details/ListDetails page templates.
I think the real problem you are running into has something to do with error handling and update panels. When debugging in IE, do you see a little exclamation point in the bottom left of the screen? If so, click on it and you will see the javascript error (Sys.WebForms.PageRequestManagerServerErrorException) that has occured because of the unhandled exception.
For more on this, check out ScottGu's Blog on the topic.
#Aaron's comment: that is too early to capture the errors he is referring to. I think, in this scenario, he wants to handle the Updated event because the EntitydataSource will not actually throw an exception until after it gives this event's handlers a chance to run: (MSDN):
If an error occurs when changes are
persisted to the data source, the
Updated event is raised and the
Exception property of the
EntityDataSourceChangedEventArgs
object is set to the returned
Exception. If you handle the exception
in the Updated event handler, set the
ExceptionHandled property to true.
This prevents the exception from being
raised again. When you specify a value
of false for the ExceptionHandled
property, the EntityDataSource
re-raises the exception.

If I am trying to update data from a DetailsView control I'd mostly rely on code behind techniques. I believe there is an ItemCommand fired when you click on any of the DetailView's standard buttons. So inside of these events you have to figure out which button fired the event and take necessary action.
But since your detailsview sits inside a gridview edit template, I suggest you wire the events manually; incorporate them in your markup manually.
...And the update you click is on the DetailsView and not the gridview; so remember to cancel the gridview's editing mode and rebind the gridview.
Hope this helps !!!

Related

Update Panel to update only portion of repeater

I have an repeater in an update panel. The repeater has a button and a grid. At runtime, there would be as many as 4 buttons to 4 grids. When button is clicked, data will be bound to the grid associated with it. I want the partial postback on the grids so that if I click one button and data is bound to grid1, if I click another button to bind grid2, I don't want to lose the data already bound to grid1.
I understand controls inside update panel causes a partial page update. But I get an error when I click on the dynamic buttons (similar to the error below).
I get an error if I try to register the button as ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl:
Error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near 'SessionSession342066'.
but I don't get an error if I register the button as ScriptManager.GetCurrent(Page).RegisterPostBackControl. However, the latter will do a full postback of the entire repeater.
Because the id's are dynamic, I can't seem to add them to the <Triggers>...
Any suggestions?
Couldn't you abandon the use of the updatepanel and use pure jQuery with web methods instead? In that way, you could update any portion of the repeater at will without a postback.

ObjectDataSource firing twice, or on its own

Can someone explain exactly how/when an ObjectDataSource fires? I have an ASP.NET page, with a GridView, which is referencing an ODS. I put a breakpoint in the method the ODS is using, and noticed it was firing twice.
I looked into the code and the answer seemed obvious at first. I had
Page_Load()
{
if(!Page.IsPostBack)
{
MethodA();
MethodB();
}
}
where MethodA and MethodB were both eventually calling gv.DataBind(). This made sense because I assume that each call to GridView.DataBind() would result in asking the ODS for data, and therefore running my data access method.
The weird thing is that when comment out the call to MethodA, it still fires twice. Checking the call stack shows the method being run first as a result of MethodB, and then again, with no trail except [External Code]. This mystery load does not happen when I let MethodA and MethodB both execute.
Any idea what's going on here? Any idea what other code I might have that is asking the ODS for data? I'm starting to think all these 'no code' data controls are more obfuscation and BS than they're worth.
I've experienced this problem when we were hiding/showing gridview column dynamically in code.
Here is a page that talks about some issues that might cause multiple Selects
http://forums.asp.net/t/1161164.aspx
Multiple calls to a gridview's databind method can occur implicitly if you're changing the visibility, i.e., showing and/or hiding, the columns of a gridview tied to an object data source.
In this scenario, try encapsulating the show/hide gridview column code in the Page_LoadComplete event handler.
The Page_LoadComplete event handler is in a prime position in the page lifecycle to prevent multiple databind calls and still be effective as it is invoked after control change events (e.g., button click, drop down selected index changed, etc.) yet before the gridview databinding events.
"when comment out the call to MethodA, it still fires twice". So it will likely be Page_Load called twice. Probably you have AutoEventWireup="true" and also registering event in code http://www.aspdeveloper.net/tiki-index.php?page=ASPFaqEventsDoubleFire
If you set the datasource of the gridview with something like
gv.DataSourceID=dsObjDataSource;
then the grid view calls gv.DataBind() on its own.
I had the same problem - the problem was that I was hiding/showing a column after, or during, databinding. Moving the hide/show code before the databinding stopped the binding from happening twice, which I suspect is the same effect as moving it to the Page_Load. In my case the databind was happening in response to a dropdown listbox change - doing the column add/remove before the DataBind() call fixed the twofer problem for me.
I was getting the same result with DataBinding occuring twice using asp:DataList and asp:ObjectDataSource.
It turned out to be because I was using a UserControl in the select parameters:
<asp:ControlParameter Name="GroupID" Type="Int32" DefaultValue="-1"
ControlID="UserControl1" PropertyName="SelectedGroupID" />
I am getting weary of UserControls. I can see how they might be productivity enhancement for 5th graders but they are a complete waste of time at a higher level.

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

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:
Working Pattern:
Page_Load on Parent Page
Page_Load on ASCX
Data Loads fine
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?
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?
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.
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.
Use both DataBind. Example:
SqlDataSource1.DataBind();
ListView1.DataBind();

purpose for <pages enableEventValidation="false">

I've used the following in web.config
<pages enableEventValidation="false">
This corrects a problem we've been having with Ajax.
We have a web page that if you browse to directly using a standard HTML hyperlink works fine.
If you browse to the page from another page via link inside a gridview and response.redirecting in the RowCommand event to the page passing an ID in the querystring. The page throws errors from controls inside the panel stating
"Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation. "
I'm happy to leave the page validation as false as it seems to have had no other effect.
Any ideas what's happening?
Read the documentation.
EDIT: For security reasons, it's probably best to leave it set to true wherever you can.
I would therefore recommend that you set it to false only on the individual AJAX pages where it causes problems, while leaving it true in web.config.
From here
Invalid PostBack or CallBack argument error is basically raise because of Event Validation feature. The EventValidation feature is a new feature in ASP.NET 2.0, and provides an additional level of checks to verify that a postback from a control on the client is really from that control and not from someone malicious using something like a cross-site script injection to try and manipulate things. It is part of our overall strategy of increasingly adding security in depth levels to the programming model -- so that developers can be secure by default even if they forget to add security checks of their own.
Now, Invalid PostBack or CallBack argument error may occur when you are firing click event and the object is rebinding or its properties are changed in Page_Load event or someone is trying to hack into your system with cross site scripting. Each time .Net Framework render a page then it associate a unique Guid for all the controls. When binding a gridview or repeater, on each databind framework will associate a new guid for the contorl. So every time when you are firing event make sure Page_Load event does not change the control, because if the control changed the it will have a different Guid which have acutally fired the event for postback. Here are some scenario with this error.
1) Invalid Postback or Callback argument in GridView Problem may be: You are binding data in Page_Load event with either Object Data Source or Manual Binding with function call. This will make your GridView bind data on every event fire of any control. When you are firing any GridView command with OnRowCommand, before RowCommand fire your GridView will rebind and all control within it will be assigned to new id. So RowCommand could not get the item which have fired the event. Solution for Invalid Postback or Callback argument in GridView: You can bind your data within this if condition
if (!IsPostBack)
{
//Your code for Bind data
}
This code will definitely give you solution if this not work then check whether any other control is not giving error.
There is one thing worth adding here: If you want to disable the event validation for a specific control, rather than the entire page, there is a workaround documented here and here (and now referenced in the relevant Connect suggestion):
Simply subclass the relevant WebControl class, and don't set the SupportsEventValidation attribute on the subclass. The subclass will be exempt from event validation.

How to process events from Buttons inside Repeaters? And what's this EnableEventValidation thing?

I have a Repeater with a Button inside the ItemTemplate. I added the CommandName property to the button and registered and event handler for the ItemCommand event on the Repeater.
My problem is that when I click the button, I get an ArgumentException with a message saying something about EnableEventValidation being set to true.
(By the way, is there a way I can get the message in English, instead of a lousy Portuguese translation?)
I tried setting it to false and the ItemCommand handler is not called. If I set it to true I get the error.
The message also says something about using ClientScriptManager.RegisterForEventValidation if I trust the client (which I do). The problem is I can't make sense of the documentation for that method.
lookout for the binding problem pointed out by Steve Robbins and you may also want to take a look at this article which I found pretty useful when I was stuck in a similar situation.
The only time I've ever seen this is when I was rebinding the repeater in the Page_Load on postback, rather than wrapping the binding in an if (!Page.IsPostBack). If you do this then the control that's sending the message is effectively invalid, so it fails.
Only Problem is Postback is Happening Before ItemCommand Event of Repeater Could happen....i.e why asp.net is throwing a Event Validation Error
If u r Binding Repeater inside Page Load Write it Inside If(!PostBack){...}

Resources