Hi Guys,

I have a data bound grid-view with action buttons for updating and deleting items in a users shopping cart. The grid-view uses a 'SelectMethod' in the code behind to generate the data. The problem I'm having is that every time I edit some data in the grid-view, the data is successfully persisted, but then an error is thrown before the page even completes loading.

Here's the exception details:

System.InvalidOperationException:

A public method with the name '' was eithernot found or there were multiple methods with the same name on the type 'ASP.posworx_cart_aspx'.

What makes it even more confusing is that (' ') is an empty string, I checked in my code and I don't even have any attributes with an empty string value, except for the header of an item template, which I don't think even matters really.

Here's the stack trace:

[InvalidOperationException: A public method with the name '' was either not found or there were multiple methods with the same name on the type 'ASP.posworx_cart_aspx'.] System.Web.UI.WebControls.ModelDataSourceView.FindMethod(String methodName) +2464454 System.Web.UI.WebControls.ModelDataSourceView.RequireAsyncModelBinding(String methodName, ModelDataSourceMethod& method) +67 System.Web.UI.WebControls.ModelDataSourceView.Update(IDictionary keys, IDictionary values, IDictionary oldValues, DataSourceViewOperationCallback callback) +97 System.Web.UI.WebControls.GridView.HandleUpdate(GridViewRow row, Int32 rowIndex, Boolean causesValidation) +1210 System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +877 System.Web.UI.WebControls.GridView.OnBubbleEvent(Object source, EventArgs e) +89 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 System.Web.UI.WebControls.GridViewRow.OnBubbleEvent(Object source, EventArgs e) +90 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 System.Web.UI.WebControls.LinkButton.OnCommand(CommandEventArgs e) +121 System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +161 System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +12 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +15 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +9754214 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3562

The markup code for my grid-view:

<div class="table-responsive unbordered">
  <asp:GridView ID="shoppingCartGridView" runat="server" DataKeyNames="ItemDetailId" SelectMethod="GetShoppingCartItems" AutoGenerateColumns="false" BorderColor="Transparent" BackColor="White" ForeColor="Black" CssClass="table table-hover table-condensed"
    OnRowUpdating="shoppingCartGridView_RowUpdating" OnRowDeleting="shoppingCartGridView_RowDeleting" ItemType="OnlineShoppingApplication.BusinessEntities.ShoppingCart.ShoppingCartItem">
    <SelectedRowStyle BackColor="#CC3333" ForeColor="White"></SelectedRowStyle>
    <SortedAscendingCellStyle BackColor="#FFF"></SortedAscendingCellStyle>
    <SortedAscendingHeaderStyle BackColor="#333333"></SortedAscendingHeaderStyle>
    <SortedDescendingCellStyle BackColor="#FFF"></SortedDescendingCellStyle>
    <SortedDescendingHeaderStyle BackColor="#333333"></SortedDescendingHeaderStyle>

    <Columns>
      <asp:TemplateField HeaderText="Product" HeaderStyle-Width="50%">
        <ItemTemplate>
          <div class="row">
            <div class="col-sm-2 hidden-xs"><img class="img-responsive" src="../Images/product-image holder.gif" alt="<%#:Item.ItemDescription%>"></div>
            <div class="col-sm-10">
              <h4 class="bold-text nomargin">
                <%#:Item.ItemDescription %>
              </h4>
              <p data-th="Product">
                <%#:Item.ItemDescription %>
              </p>
            </div>
          </div>
        </ItemTemplate>
      </asp:TemplateField>
      <asp:BoundField DataField="ItemDetailId" HeaderText="Id" SortExpression="ItemDetailId" Visible="false" />
      <%--<asp:TemplateField HeaderText="Name">
                <ItemTemplate>
               <a class="btn-link bold-text" href="<%#: GetRouteUrl("ProductByIdRoute", new {productId = Item.ItemId,productDetailId = Item.ItemDetailId})%>">
        <%#:Item.ItemDescription%>
          </a>
          </ItemTemplate>
          </asp:TemplateField>--%>
          <asp:BoundField DataField="ItemPrice" ItemStyle-CssClass="btn-link item-vertical-align" HeaderText="Price" HeaderStyle-Width="10%" DataFormatString="{0:c}" />
          <asp:TemplateField HeaderText="Quantity" HeaderStyle-Width="8%">
            <ItemTemplate>
              <asp:TextBox ID="quantityTextBox" runat="server" CssClass="form-control text-center" Text="<%#:Item.Quantity %>" TextMode="Number"></asp:TextBox>
            </ItemTemplate>
          </asp:TemplateField>
          <asp:TemplateField HeaderText="Subtotal" HeaderStyle-Width="22%" HeaderStyle-CssClass="text-center" ItemStyle-CssClass="btn-link text-center">
            <ItemTemplate>
              <%#:$"{(Convert.ToDouble(Item.Quantity)) * (Convert.ToDouble(Item.ItemPrice)):c}"%>
            </ItemTemplate>
          </asp:TemplateField>
          <asp:TemplateField HeaderText="" HeaderStyle-Width="10%">
            <ItemTemplate>
              <asp:LinkButton ID="updateCartItemButton" runat="server" CssClass="btn btn-info btn-sm" Text='<i class="fa fa-refresh"></i>' alt="Update item" CommandName="Update">
              </asp:LinkButton>

              <asp:LinkButton ID="deleteCartItemButton" runat="server" CssClass="btn btn-danger btn-sm" Text='<i class="fa fa-trash-o"></i>' alt="Delete item" CommandName="Delete">
              </asp:LinkButton>
            </ItemTemplate>
          </asp:TemplateField>
    </Columns>

    <EmptyDataTemplate>
      <div class="row alert alert-warning alert-dismissable fade in" style="margin-bottom:0px">
        There are no items in your shopping cart
      </div>
    </EmptyDataTemplate>

    <EmptyDataTemplate>
      <div class="row alert alert-warning alert-dismissable fade in" style="margin-bottom:0px">
        There are no items in your shopping cart
      </div>
    </EmptyDataTemplate>
  </asp:GridView>
</div>
</div>

Select method for grid-view:

public IQueryable<BusinessEntities.ShoppingCart.ShoppingCartItem> GetShoppingCartItems()
    {
        IQueryable<BusinessEntities.ShoppingCart.ShoppingCartItem> shoppingCartItems = _cartService.GetCartItems(SiteMaster.Customer.CustomerGuid).AsQueryable();
        if (shoppingCartItems != null)
        {
            CreateCartSummary();    
        }
        return shoppingCartItems;
    }

Finally the

shoppingCartGridView_RowUpdating Event method:

protected void shoppingCartGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    try
    {
        int prouductDetailId = (int)shoppingCartGridView.DataKeys[e.RowIndex].Value;
        TextBox quantityTextBox = (TextBox)shoppingCartGridView.Rows[e.RowIndex].FindControl("quantityTextBox");
        int newQuantity = int.Parse(quantityTextBox.Text);
        UpdateCartItem(prouductDetailId, newQuantity);
        DisplayMessage("Your cart has been updated successfully", Bootstrap.MessageType.Success);
        shoppingCartGridView.DataBind();
    }
    catch (Exception ex)
    {
        ExceptionUtility.LogException(ex, $"{this}");
    }
}

And the

shoppingCartGridView_RowDeleting Event method:

protected void shoppingCartGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        try
        {
            int productDetailId = (int)shoppingCartGridView.DataKeys[e.RowIndex].Value;
            RemoveCartItem(productDetailId);
            DisplayMessage("The item has been deleted from your cart", Bootstrap.MessageType.Success);
            shoppingCartGridView.DataBind();
        }
        catch(Exception ex)
        {
            ExceptionUtility.LogException(ex, $"{this}");
            DisplayMessage(@"An error occured while deleting the item from the cart
                             please try again later", Bootstrap.MessageType.Danger);
        }
    }

Thanks in advance guys, I would highly appreciate some assistance on this, because I really don't know what to do.

I guess your last method call was something like FindMethod(methodName) (See your stack trace)
First thing were I'd look: Does methodName have a name?

Yes it does, look at the 'SelectMethod' Attribute of the GridView. Its called 'GetShoppingCartItems'. That's the only method thats involved in
populating the gridview, other than that there's no other methods that involve interaction with the GridView besides the update and delete operations, which are triggered when either the delete or update button in the GridView is clicked

Yes, in the attributes you have a SelectMethod, your stack trace stops at a FindMethod, shouldn't that make any difference?

Well that's the problem, I don't know why its trying to find another method, because the only method that the grid-view is dependant on for population is the 'SelectMethod', other than that I don't know, where, how or why the FindMethod method appears in the stack trace, because there's certainly no
FindMethod attribute for the grid-view.

FindMethod comes out of ModelDataSourceView not out of GridView.
At least this is showing in the stack trace.

Ohkay now where does ModelDataSourceView come into play? And why is it causing this problem? I read some of Microsoft's documentation regarding the data source view class, as usual, a quite foggy description.

I'm not that knowledgeable in ASP, but AFAIKS your GridView is doing an update whereby it calls this ModelDataSourceView method. Can debug to follow all this and see what happens?

Ohkay I see. Thanks for trying though maan! I really appreciate it.

I'm not sure if I'm understanding your question though, do you want me to replicate the error for you so that you can
have a chance to see if you can manage o solve it?

I forgot the "you" in the sentence Can debug to follow all this and see what happens? so that was a bit unclear I guess. I meant if you can debug it to see what happens with certain variables. Tell me what you came up with. If we could sit beside each other at the same terminal, would probably help also. lol

Thank you sooooo much!!! I can't say you that you solved the problem for me, but you difinately did guide me :) wouldn't have figured it out without you, I really appreciate your help and patience.
After doing some research on the ModelDataSourceView class, I found that there are properties of the class called UpdateMethod,DeleteMethod,InsertMethod (basically properties to specify the names of all the CRUD operations) .Which then made me think that instead of having the OnRowUpdating and OnRowDeleting events fired when I update a row, why not just add an UpdateMethod attribute to the GridView(with the value of that attribute being the name of the method responsible for performing the update operation)? After all there was already a SelectMethod attribute, so it kinda made more sense to have the UpdateMethod and DeleteMethod attribute to go along with it instead of OnRowUpdating and OnRowDeleting.

Aaaaand Walaaa!!!!! IT WORKS perfectly.

Hé man, glad I could be of some guidance, sometimes that is all that is needed. :)
Keep up the good work! And as you see the solution is sometimes looking close at a stack trace.
Over and out.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.