0

I have a partial view for editing a collection (most of which I've truncated here):

@using CustomSurveyTool.Models
@model Basiclife
<div class="editorRow">
    @using (Html.BeginCollectionItem(""))
    {
        <div class="form-horizontal">
            <div class="row">
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })

                <div class="col-md-2">
                    @Html.LabelFor(model => model.Plantype, htmlAttributes: new { @class = "control-label" })

                    @Html.EditorFor(model => model.Plantype, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Plantype, "", new { @class = "text-danger" })
                </div>
                <div class="col-md-1">
                    <a href="#" class="deleteRow">X</a>
                </div>
            </div>
        </div>
    }
</div>

Which is part of a wrapper view:

@using CustomSurveyTool.Models
@model IEnumerable<Basiclife>
@{
    ViewBag.Title = "CreateBasicLifeResponse";
}

<h2>Basic Life Insurance Plans</h2>
<div id="planList">
    @using (Html.BeginForm())
    {
        <div id="editorRows">
            @foreach (var item in Model)
            {
                @Html.Partial("_BasicLifeResponse", item)
                }
        </div>
        @Html.ActionLink("Add", "BasicLifeResponse", null, new { id = "addItem", @class = "button" });
        <input type="submit" value="submit" />
    }
</div>

Which posts back to this controller:

    [HttpPost]
    public ActionResult CreateBasicLifeResponse(IEnumerable<Basiclife> model)
    {

        foreach(var item in model)
        {
            string currentUserId = User.Identity.GetUserId();
            Response targetresponse = db.response.FirstOrDefault(x => x.Userid == currentUserId);
            int responseid = targetresponse.Id;
            item.ResponseId = responseid;
            db.basiclife.Add(item);
            db.SaveChanges();
        }

        List<Basiclife> basiclife = new List<Basiclife>();
        return View(model);
    }

I am getting a NullReferenceException on the foreach(var item in model) after submitting the form. What could be causing this?

superblowncolon
  • 153
  • 1
  • 10
  • First of all use network sniffer (e.g. fiddler or your browsers built in developer tool) and look for yourself what is sent to the server. Is the request body valid form encoded content? Repeating a form will most likely result in repeated fields with same name that wont be parsed by the model binder as you expect. Either declare an input model that fits the data sent by the client or you better gather the data from the forms into a json array that will be parseable to the model you are currently using. – ZorgoZ Oct 01 '18 at 19:45
  • Possible duplicate of [How to pass IEnumerable list to controller in MVC including checkbox state?](https://stackoverflow.com/questions/17037858/how-to-pass-ienumerable-list-to-controller-in-mvc-including-checkbox-state) – akerra Oct 01 '18 at 20:15
  • You cannot use an `EditorTemplate` for dynamically adding new collection items. Refer [this answer](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) for some options, and [this one](http://stackoverflow.com/questions/40539321/partial-view-passing-a-collection-using-the-html-begincollectionitem-helper/40541892#40541892) for a detailed implementation using `BeginCollectionItem` –  Oct 01 '18 at 22:04
  • I do not see an example with MVC5. Can BeginCollectionItem still be used? The Github repo hasn’t been updated in 6 years. – superblowncolon Oct 02 '18 at 01:19
  • The 2nd link I gave you contains the full code for an example using `BeginCollectionItem` (and its still relevant) –  Oct 03 '18 at 01:17
  • @StephenMuecke My apologies - thanks for following up on this. I've implemented the code identically above; any idea why I'm getting a NullReferenceException now? – superblowncolon Oct 03 '18 at 13:43
  • You have not implemented it identically! For a start it would need to be `@using (Html.BeginCollectionItem(""))` - your model is `IEnumerable` and does not contain a property named `basiclives`. And in the controlleriIt needs to be `return View(model);`, not `return View(basiclife);` –  Oct 03 '18 at 21:22
  • @StephenMuecke Thanks again for all your help. I have updated the code above; the error persists. – superblowncolon Oct 03 '18 at 21:52
  • Stop changing your question! You are invalidating the comments and answers that have been added. The code you have now shown works fine (it will generate inputs with `name=[xxx].Plantype` where `xxx` is a `Guid`). Refer also [MVC BeginCollectionItem](https://stackoverflow.com/questions/48647855/mvc-begincollectionitem/48654410#48654410) –  Oct 03 '18 at 21:59
  • @StephenMuecke I understand. The part that's confusing me, then, is how to access items that are enumerated as GUIDs to add them all to database? Clearly I can't increment a for loop from 1 to X, and I also can't use a foreach loop since it was throwing the NullReferenceException. – superblowncolon Oct 03 '18 at 22:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/181252/discussion-between-stephen-muecke-and-ats1958). –  Oct 03 '18 at 22:52

1 Answers1

0

You need to follow the MVC naming convention which involves using a for loop with an index instead of foreach in your Razor view. Check out this article: How to pass IEnumerable list to controller in MVC including checkbox state?. I would recommend the Editor Template approach described in the article, it is most similar to your current PartialView approach.

akerra
  • 427
  • 3
  • 16
  • I don't understand how my needs are different from the solution here: https://stackoverflow.com/questions/40539321/a-partial-view-passing-a-collection-using-the-html-begincollectionitem-helper/40541892#40541892 – superblowncolon Oct 01 '18 at 20:41
  • You are not using `Html.BeginCollectionElement()` as in the solution you referenced, which would be another way to adhere to the MVC naming convention. – akerra Oct 01 '18 at 20:50
  • I implemented this per the link above and now the NullReferenceException is on `for(var i=0; i < response.Count; i++)` – superblowncolon Oct 01 '18 at 21:00