0

I have been trying to select multiple rows from my table of data(Generated using EF) and then pass all selected rows to the next view to perform some action. On passing the data to the next view i am getting the following error :

System.NullReferenceException: 'Object reference not set to an instance of an object.' Temporary local of type 'int[]'> was null.

Any help on how to solve this will be appreciated.

Below is my code:

View:

<div class="row">
  <div class="col-md-12">
    <!-- Advanced Tables -->
    <div class="panel panel-default">
      <div class="panel-heading">
        @using (Html.BeginForm()) {
        <form action="#" method="post">
          <label>Search by Company Name:</label> @Html.TextBox("SearchString")
          <input type="submit" value="Go" placeholder="Search" style="background-color: #0a9dbd; color: white; border-color: #0a9dbd;"> &nbsp; &nbsp;
          <label>Search by Card Number:</label> @Html.TextBox("searchCard")
          <input type="submit" value="Go" placeholder="Search" style="background-color: #0a9dbd; color: white; border-color: #0a9dbd;"> &nbsp; &nbsp;
          <a href="ExportToExcel">Export to Excel</a>
        </form>

        }
      </div>

      <div class="panel-body">
        <a href="@Url.Action(" Create ","CustomerView ")" class="btn btn-primary">Add Gift Card</a>
        <a href="@Url.Action(" GetBalance ", "CustomerView ")" class="btn btn-primary">Get Card Balance</a>
        <a href="@Url.Action(" PostCards ", "CustomerView ")" class="btn btn-primary">Load Cards</a>

        <br />
        <br />
        <div class="table-responsive">
          <table class="table table-striped table-bordered table-hover" id="dataTables-example">
            <thead>
              <tr>
                <th>Card ID</th>
                <th>Company</th>
                <th>Card Number</th>
                <th>Card Number 2</th>
                <th>Date Created</th>
                <th>Card Status</th>
                <th>Discount Level ID</th>
                <th>Loyalty Level ID</th>
                <th>Gift Card Enabled</th>
                <th>Loyalty Enabled</th>
                <th></th>

              </tr>
            </thead>
            <tbody>
              @foreach (var item in Model) {
              <tr>
                <td><input type="checkbox" name="ids" value="@item.CardID" /></td>
                <td>@item.CardID</td>
                <td>@item.Customer.CustomerCompanyName</td>
                <td>@item.CardNumber</td>
                <td>@item.CardNumber2</td>
                <td>@item.CardDate</td>
                <td>@item.CardStatus</td>
                <td>@item.DiscountLevelID</td>
                <td>@item.LoyaltyLevelID</td>
                <td>@item.GiftCardEnabled</td>
                <td>@item.LoyaltyEnabled</td>


                <td>
                  <a href="@Url.Action(" Edit ","CustomerView ", new {id = item.CardID} )" class="btn btn-primary"><i class="fa fa-edit "></i> Edit</a> <br />

                </td>

              </tr>
              }
            </tbody>

          </table>
          Page @(Model.PageCount
          < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount @Html.PagedListPager(Model, page=> Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
        </div>

      </div>
    </div>
    <!--End Advanced Tables -->
  </div>
</div>

Controller:

public ActionResult PostCards(int[]ids)
        {
            var myObject = new Card();

            foreach(var id in ids)
            {
                myObject = db.Cards.Single(o => o.CardID == id);
                return RedirectToAction("LoadCards", myObject);
            }

            return View();
        }


        public ActionResult LoadCards()
        {
            return View();
        }

I need the selected data to be passed to the LoadCards view.

Janine Alexander
  • 151
  • 4
  • 22
  • Your checkboxes are not inside the `
    ` element (so they do not post a value and hence the `ids` parameter is `null`). Not only that, you have nested forms which are invalid and not supported
    –  Nov 27 '17 at 11:33
  • And your controller method method makes no sense anyway - your have a loop with a `return RedirectToAction()` which means you exit the method during the first iteration. –  Nov 27 '17 at 12:06
  • Yep thanks. I managed to figure that out and got it working – Janine Alexander Nov 28 '17 at 05:23

1 Answers1

0

Let us first look at the NullReference you are getting. The problem here is that no correct index is created to bind the checkboxes to an array. Use a for loop instead of foreach. In MVC/Razor, how do I get the values of multiple checkboxes and pass them all to the controller?

To get the desired behaviour:

  • change the foreach to a for loop so the correct indices for sending the data will be created.
  • add a checkbox in each row that lets the user select the rows to submit.
  • your action should recieve a collection of models for each row. This model always transports the CardId and tells us whether it was selected.

    public class SelectedCardModel {
    
        public int CardId { get; set; }
        public bool IsSelected {get; set;}
    }
    

In the view:

@using (Html.BeginForm("PostCards", "CustomerView", FormMethod.Post) {
    // <table> etc ... 
    <tbody>
    @for (var i = 0; i < Model.Count; i++) {
        @{ var item = Model.ElementAt(i); }
        <tr>
            <td>
                @Html.Hidden("CardId[" + i + "]")
                @Html.CheckBox("IsSelected[" + i + "]")
            </td>
            // display other properties of item ...
            <td>@item.CardID</td>
            // ...
        </tr>
    }
    </tbody>
    </table>
    <button type="submit">Load Cards</button>
}

Action:

[HttpPost]
public ActionResult PostCards(SelectedCardModel[] selectedCards) {
    foreach(var card in selectedCards) {
        if (card.IsSelected) {
            var selectedId = card.CardId;
            // ...
        }
    }
}
Georg Patscheider
  • 9,357
  • 1
  • 26
  • 36
  • Collection indexers are not required in this case - the parameter is an array of simpkle types (collection indexers are only required for collections of complex objects –  Nov 27 '17 at 11:31