locked
How to resolve "not find a non-generic method" for ListView when ConflictDetection is on. RRS feed

  • Question

  • User-1794604719 posted
    Hi, This problem is driving me crazy. :( My ListView uses an ObjectDataSource as below: <asp:ListView ID="UserListView" runat="server" ConvertEmptyStringToNull="true" DataSourceID="UserDataSource" DataKeyNames="ID" OnItemDataBound="UserListView_OnItemDataBound"> …… </asp:ListView> <asp:ObjectDataSource ID="UserDataSource" TypeName="TestLayout.UserDataTable" ConflictDetection="CompareAllValues" OldValuesParameterFormatString="old_{0}" SelectMethod="SelectUsers" DeleteMethod="DeleteUser" runat="server"> <DeleteParameters> <asp:Parameter Name="ID" Type="Int32" /> <asp:Parameter Name="Role" Type=" Int32" /> <asp:Parameter Name="old_Role" Type=" Int32" /> </DeleteParameters> …… </asp:ObjectDataSource> The Type that the ObjectDataSource uses is: public class UserDataTable { DBAccessor db; /// <summary> /// Ctor /// </summary> public UserDataTable() { db = new DBAccessor(); } [DataObjectMethod(DataObjectMethodType.Select)] public DataTable SelectUsers() { Collection<UserInfo> users = null; users = db.GetUsers(); DataTable resultTable = new DataTable(); DataColumn colItem0 = new DataColumn("ID", Type.GetType("System.Int32")); resultTable.Columns.Add(colItem0); DataColumn colItem1 = new DataColumn("Role", Type.GetType("System.Int32")); resultTable.Columns.Add(colItem1); for (int i = 0; i < users.Count; ++i) { DataRow row = resultTable.NewRow(); row["ID"] = i + 1; row["Role"] = users[i].role; resultTable.Rows.Add(row); } return resultTable; } [DataObjectMethod(DataObjectMethodType.Delete)] public void DeleteUser(int ID, int Role, int old_Role) { db.DeleteUser(ID, Role, old_Role); } } My observations are: 1. Above code will make the page show the notorious error: ObjectDataSource 'UserDataSource' could not find a non-generic method 'DeleteUser' that has parameters: …… 2. If I remove DataKeyNames="ID" in ListView, then the page will not show any error but the parameters of DeleteUser will all be 0 for int (or null for string). MSDN says that “You must set the DataKeyNames property for the automatic updating and deleting features of the GridView control to work. The values of these key fields are passed to the data source control in order to match the row to update or delete. ” So I think it is a by-design behavior that the DeleteUser parameters are 0 if I do not set DataKeyNames. However, I have trouble to bypass the error described in observation 1. There are a lot of discussion about this error online. But none of them apples to my case. For example, one suggested workaround is to replace OldValuesParameterFormatString="old_{0}" to OldValuesParameterFormatString="{0}". This “fix” disables Conflict Detection which is unacceptable in my case. Another suggested workaround is to make the primary key column as editable and remove primary key from update/delete query. But that suggest is for GridView and for auto-generated code. I am using ListView and 100% manually written code. Could anybody give some hint how to resolve the issue of “could not find a non-generic method” in my case? Thanks a lot Leon
    Sunday, January 11, 2009 6:04 PM

Answers

  • User-260435932 posted

    First thing you'd want to do is to properly format your code.Secondly this is a common mistake that people make when using ODS with conflict detection, so common that people have written blog posts on how to solve the "not able to find a generic method problem" when its really not a problem in the first place. The REAL problem is you have to know how you need to define your method such that ObjectDataSource can find it.

    For every field in DataKeyNames there needs to be a parameter for on your method. So
    <asp:ObjectDataSource OldValuesFormatString="old_{0}" .../>
    <asp:ListView DataKeyNames="Foo,Bar" .../>

    Your method minimally needs will need parametrs foo, bar, old_foo, and old_bar. Other parameters come from the databound control, so every <%# Bind("") %> statement in the case of your listview will be a parameter and they are all CASE INSENSITIVE. The last set of parameters comes from the actual parameter collections that are defined on the datasource i.e. UpdateParameters, DeleteParameters etc.

    One you put this knowledge together you should know how to define your method so that it can be found correctly. If your really curious, download reflector and take a look at ObjectDataSourceView class in System.Web.

    Hope this helps

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 14, 2009 5:58 AM

All replies

  • User-260435932 posted

    First thing you'd want to do is to properly format your code.Secondly this is a common mistake that people make when using ODS with conflict detection, so common that people have written blog posts on how to solve the "not able to find a generic method problem" when its really not a problem in the first place. The REAL problem is you have to know how you need to define your method such that ObjectDataSource can find it.

    For every field in DataKeyNames there needs to be a parameter for on your method. So
    <asp:ObjectDataSource OldValuesFormatString="old_{0}" .../>
    <asp:ListView DataKeyNames="Foo,Bar" .../>

    Your method minimally needs will need parametrs foo, bar, old_foo, and old_bar. Other parameters come from the databound control, so every <%# Bind("") %> statement in the case of your listview will be a parameter and they are all CASE INSENSITIVE. The last set of parameters comes from the actual parameter collections that are defined on the datasource i.e. UpdateParameters, DeleteParameters etc.

    One you put this knowledge together you should know how to define your method so that it can be found correctly. If your really curious, download reflector and take a look at ObjectDataSourceView class in System.Web.

    Hope this helps

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 14, 2009 5:58 AM