0

I have an ASP.NET 4.5.6 MVC 5 app. Here's the summary of my models/views/controllers:

Model classes

public class ViewModelA {
    public ViewModelB CurrentItem { get; set; }
    // ...
}

public class ViewModelB {
    public List<Parameter> Parameters { get; set; }
    // ...
}

public class Parameter {
    public string Name { get; set; }
    public int Position { get; set; }
    // ...
}

View

@model ViewModelA

@* ... *@

@for (int i = 0; i < Model.CurrentItem.Parameters.Count; i++) {
    @Html.EditorFor(m => m.CurrentItem.Parameters[i])
}

~/Views/Shared/EditorTemplates/Parameter.cshtml

@model Parameter

<tr>
    <td class="col-md-3">
    </td>
    <td class="col-md-9">
        @Html.TextBoxFor(m => m.Position)
        @Html.TextBoxFor(m => m.Name)

        @* Model.Position always equals list index + 1 *@
        <button type="submit" class="btn btn-default" formaction="@Url.Action("DeleteParameter", "MyController", new { deleteIndex = (Model.Position - 1) })" for formmethod="post" title="Delete parameter">
            <i class="glyphicon glyphicon-minus"></i>
        </button>

        <!-- Debug only -->
        <span>Position = @Model.Position  |  Name = @Model.Name</span>
    </td>
</tr>

Controller actions

[HttpPost]
public ActionResult AddParameter(ViewModelA viewModel) {
    var p = new Parameter() {
        Name = "",
        Position = (byte)(viewModel.CurrentItem.Parameters.Count + 1)
        //...
    };

    viewModel.CurrentItem.Parameters.Add(p);

    return View("Edit", viewModel);
}

[HttpPost]
public ActionResult DeleteParameter(int deleteIndex, ViewModelA viewModel) {
    viewModel.CurrentItem.Parameters.RemoveAt(deleteIndex);

    for (int i = deleteIndex; i < viewModel.CurrentItem.Parameters.Count; i++) {
        viewModel.CurrentItem.Parameters[i].Position--;
    }

    return View("Edit", viewModel);
}

Here is an image that shows a series of screenshots after adding a couple of parameters, then deleting one. Horizontal red lines separate each screen after refresh.

Add and delete parameter

After deleting the parameter in position 1, I would expect the remaining parameter to have the name "Name2", but it still shows "Name1" (even though the "debug span text" shows the right name). The controller and model seem to be doing what I expect. Why is the textbox in the view showing the wrong name?

neizan
  • 2,291
  • 2
  • 37
  • 52
  • The behavior is explained in [this answer](http://stackoverflow.com/questions/35605740/incorrect-list-model-binding-indices-when-using-html-helpers/35640658#35640658). And as a side note, its just `@Html.EditorFor(m => m.CurrentItem.Parameters)` - no loops (the `EditorFor()` method accepts `IEnumerable` and generates the correct html for each object in the collection –  Mar 27 '17 at 21:26
  • However your code is terribly inefficient -posting back the whole collection just to add or remove one item. Consider the answers [here](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) and [here](http://stackoverflow.com/questions/40539321/a-partial-view-passing-a-collection-using-the-html-begincollectionitem-helper/40541892#40541892) –  Mar 27 '17 at 21:30
  • @StephenMuecke Thanks for the link to your other answer. It does indeed answer my question. I upvoted a couple of your other answers, but feel free to post one here, and I'll gladly accept. As an aside, I know the code is inefficient--that's not a concern for this particular app. Thanks again! – neizan Mar 28 '17 at 11:50

0 Answers0