0

When my Index view display 2 people and none of them are selected the model validation works correctly due to the MinLengthAttribute in .NET 4.5.

Now comes my custom logic in the ui. When only one person is displayed in the Index view I need no checkbox to check it. The customer can directly press the submit button. I try to manually fill the SelectedIds array see the @else clause.

But this code: Model.SelectedIds = new int[]{ item.PersonId};

Does NOT work, the viewmodel.SelectedIds property on server side action is always {int[0]}

How can I still assign the one person id to the SelectedIds array?

VIEW

   @model ListTest.Models.PeopleListViewModel


@{
    var hasMoreThanOnePerson = @Model.People.Count > 1;   
}

@Html.BeginForm("Save", "Home")
{

@Html.ValidationSummary(false)

<table>
    @foreach (var item in Model.People)
    {
        <tr>
            @if (hasMoreThanOnePerson)
            {
                <td>
                    <input type="checkbox" name="SelectedIds" value="@item.PersonId" />
                </td>
            }
            else
            {
                Model.SelectedIds = new int[]{ item.PersonId};
            }

            <td>
                <input type="text" value="@item.Name" />
            </td>
        </tr>
    }
</table>
<input type="submit" value="Save" />
}

VIEWMODEL

public class PeopleListViewModel
    {
        public PeopleListViewModel()
        {
            SelectedIds = new int[] { };
        }

        [MinLength(1, ErrorMessage = "Minimum one person must be selected!")]
        public int[] SelectedIds { get; set; }

        public List<Person> People { get; set; }
    }

CONTROLLER

public ActionResult Index()
{ 
    var people = new List<Person> {
        new Person { Name = "Horst", PersonId = 10 }, 
        new Person { Name = "Michael", PersonId = 20} 
    };

    return View(new PeopleListViewModel { People = people });
}

[HttpPost]
public ActionResult Save(PeopleListViewModel viewModel)
{

    if (ModelState.IsValid)
    { 

    }

    viewModel.People = new List<Person> { new Person { Name = "Horst", PersonId = 10 }, new Person { Name = "bernarnd", PersonId = 20 } };

    return View("Index", viewModel);
}
svick
  • 236,525
  • 50
  • 385
  • 514
Elisabeth
  • 20,496
  • 52
  • 200
  • 321
  • 2
    `Model.SelectedIds = new int[]{ item.PersonId};` just sets the value on the server before its sent to the client. You never render any input for the `SelectedIds` properties when there is only one person so nothing is posted back, therefore `SelectedIds` is an empty array on postback and validation fails. –  Mar 16 '15 at 21:20
  • hope [this](http://stackoverflow.com/a/13361607/1849444) and [this](http://stackoverflow.com/a/24407593/1849444) answer will help you – teo van kot Mar 16 '15 at 21:24

1 Answers1

0

You might consider rendering a hidden field in this case to ensure that this value will be sent back to your server:

@if (hasMoreThanOnePerson)
{
    <td>
        <input type="checkbox" name="SelectedIds" value="@item.PersonId" />
    </td>
}
else
{
    @Html.Hidden("SelectedIds", item.PersonId)
}

But obviously a much better approach is to handle this on the server - which means that if there's no value assigned in the view model you will simply fetch it back from the backend because the user didn't have the chance to modify this value in the UI since there was no corresponding input element he could manipulate.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • ahr... I was so near. I also thought about HiddenFor and did not see the solution... Thanks Darin that worked! – Elisabeth Mar 16 '15 at 21:34