Clifton Steenkamp
Clifton Steenkamp

Reputation: 167

A public method with the name '' was either not found

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.

Upvotes: 1

Views: 2185

Answers (1)

Clifton Steenkamp
Clifton Steenkamp

Reputation: 167

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 the OnRowUpdating and OnRowDeleting events being fired.

Aaaaand Walaaa!!!!! IT WORKS perfectly.

So my grid-view now looks like this(all I done was removed the OnRowUpdating attribute and added the UpdateMethod Attribute and of course, I replaced OnRowDeleting with DeleteMethod):

<asp:GridView
            ID="ShoppingCartGridView"
            runat="server"
            DataKeyNames="ItemDetailId"
            SelectMethod="GetShoppingCartItems"
            UpdateMethod="ShoppingCartGridView_UpdateItem"
            DeleteMethod="ShoppingCartGridView_DeleteItem"
            AutoGenerateColumns="false"
            BorderColor="Transparent"
            BackColor="White"
            ForeColor="Black"
            CssClass="table table-hover table-condensed"
            OnDataBound="ShoppingCartGridView_DataBound"
            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-sm 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">
                                    <a
                                        href="<%#:GetRouteUrl("ProductByIdRoute", new {productId = Item.ItemId,productDetailId = Item.ItemDetailId})%>"
                                        class="btn-link"><%#:$"{Item.SizeCurve} {Item.Colour} {Item.ItemDescription}"%>
                                    </a>
                                </p>
                            </div>
                        </div>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="ItemDetailId" HeaderText="Id" SortExpression="ItemDetailId" Visible="false" />
               <asp:BoundField DataField="ItemPrice"  ItemStyle-CssClass="currency item-vertical-align" HeaderText="Price" HeaderStyle-Width="10%" DataFormatString="{0:F2}"/>
                <asp:TemplateField HeaderText="Quantity" HeaderStyle-Width="8%">
                    <ItemTemplate>
                        <asp:TextBox ID="quantityTextBox" runat="server" CssClass="form-control text-center" Text="<%#:Convert.ToInt32(Item.Quantity) %>" TextMode="Number"></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Subtotal" HeaderStyle-Width="22%" HeaderStyle-CssClass="text-center" ItemStyle-CssClass="text-center">
                    <ItemTemplate>
                        <%#:$"{Convert.ToInt32((Convert.ToDouble(Item.Quantity)) * (Convert.ToDouble(Item.ItemPrice)))}"%>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText=" " HeaderStyle-Width="10%" ItemStyle-CssClass="action">
                    <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>

Here's my new, but not so different UpdateMethod referenced in the grid-view:

public void shoppingCartGridView_UpdateItem(int ItemDetailId)
   {
        try
        {
            int rowIndex = GetRowIndexByItemDetailId(ItemDetailId);
            TextBox quantityTextBox = (TextBox)ShoppingCartGridView.Rows[rowIndex].FindControl("quantityTextBox");
            int newQuantity = int.Parse(quantityTextBox.Text);
            UpdateCartItem(ItemDetailId, newQuantity);
            DisplayMessage("Your cart has been updated successfully", Bootstrap.MessageType.Success);
            ShoppingCartGridView.DataBind();
        }
        catch (Exception ex)
        {
            ExceptionUtility.LogException(ex, $"{this}");
            DisplayMessage(@"An error occured while updating your cart item, 
                             please try again in a moment", Bootstrap.MessageType.Danger);
        }
    }

Upvotes: 1

Related Questions