Monthly Archives: May 2009

A Common ObjectDataSource Error – Update

In my previous post, I outlined a scenario whereby I could not figure out how an ObjectDataSource could be passing a parameter to a method in the business layer, where there was no such parameter in the declarative  markup for the ObjectDataSource. I have since found the answer in this article.

In a nutshell, if a GridView contains a non-read-only field in its edit template, then even if there is no corresponding parameter for that field  in the ObjectDataSource, the GridView will add one for it to the parameters collection of the ObjectDataSource. This diagram tells the story.

Mystery solved!

A Common ObjectDataSource Error

Updatesee this post where I find the answer to the mystery.

There’s a pretty common error when working with ObjectDataSources which goes something like:

ObjectDataSource ‘ObjectDataSource1’ could not find a non-generic method ‘RemoveProduct’ that has parameters: ProductId, original_ProductId.
I recently got this error when making a call to my business layer. To set the scene, I was using a very modest GridView with a small products table as the DataSource:
A simple databound GridView

A simple databound GridView

Specifically, my ObjectDataSource was calling a delete method which took one parameter of the type long i.e. public static bool RemoveProduct(long ProductId). And from the error message above, we can see that there is a mismatch between the formal parameter of the method (i.e. ProductId), and the actual parameters which were sent by the ObjectDataSource (i.e. ProductId AND original_ProductId). So, my first port of call was to check the declarative markup. It went something like this:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
	DeleteMethod="RemoveProduct" InsertMethod="AddProduct"
	OldValuesParameterFormatString="original_{0}"
	ondeleting="ObjectDataSource1_Deleting" SelectMethod="GetAllProducts"
	TypeName="BusinessTier.Business" UpdateMethod="UpdateProducts"
	onupdating="ObjectDataSource1_Updating">
	<DeleteParameters>
		<asp:Parameter Name="ProductId" Type="Int64" />
	</DeleteParameters>

… </asp:ObjectDataSource>

From that, we can see that there is only one parameter which is supposed to be sent to the delete method (i.e. ProductId). So what the heck is going on?!! I really wanted to dig into this, to figure out what was going on with the parameters that the ObjectDataSource was sending. To that end, I handled the Deleting event of the ObjectDataSource and added a little code which displays the values of the two parameters actually being passed in by the ObjectDataSource . That code is:

protected void ObjectDataSource1_Deleting(object sender, ObjectDataSourceMethodEventArgs e)
{
	/**************  debug helper **************/
	e.Cancel = true;
	foreach (DictionaryEntry dic in e.InputParameters)
		Response.Write(dic.Key + &quot;: &quot; + (dic.Value ?? &quot;null&quot;) + &quot;&amp;lt;br /&amp;gt;&quot;);
}
Looking at what I have done there, you need to cancel the event to prevent the error from being thrown. Then, you can display to the screen the values of the actual parameters. If any of the parameters have a null value, the string “null” will be displayed as the value for that parameter. Looking at the result of my handling of that event, we can see that ProductId has a value of null, and original_ProductId has a value corresponding to the product ID for the actual product which was selected for deletion:
gridview with parameter values displayed (at top of page)

The two parameter values are in black text above the GridView

My first attempt to fix this, was to populate the value of the ProductId parameter with the value that original_ProductId had, and then to remove original_ProductId from the InputParameters collection. The code for that is:

protected void ObjectDataSource1_Deleting(object sender, ObjectDataSourceMethodEventArgs e)
{
	e.InputParameters[&quot;ProductID&quot;] = e.InputParameters[&quot;original_ProductID&quot;];
	e.InputParameters.Remove(&quot;original_ProductID&quot;);
}

This worked. It totally fixed the problem and the Deleting event proceeded without error.

A colleague, however, found another way to sort this problem out. Basically, he changed the attribute OldValuesParameterFormatString=”original_{0}” in the ObjectDataSource to OldValuesParameterFormatString=”{0}”, and completely deleted the DeleteParameter:
<DeleteParameters>
<asp:Parameter Name=”ProductId” Type=”Int64″ />
</DeleteParameters>

So we see there two approaches at fixing this error. To me, both seem like hacks. I’m not sure which approach would be considered best practice. At least with the first approach, you are able to diagnose what is going on behind the scenes, and are not just placing blind trust in the ObjectDataSource responding to declarative programming. If there is another better approach out there which is considered best practice, I would invite anyone who totally understands what is going in here to chime in with their thoughts.