Home > database >  ASP.NET Core MVC : post list of list Index was out of range error
ASP.NET Core MVC : post list of list Index was out of range error

Time:12-20

I need to post list of objects inside form and it contains another list, but I got this error :

Index was out of range. Must be non-negative and less than the size of the collection

My model classes:

public class SurveyQuestionDto
{
    public SurveyQuestionDto()
    {
        SurveyChoices = new List<SurveyChoiceDto>();
    }

    public int SurveyQuesId { get; set; }
    public DateTime? DateStart { get; set; }
    public DateTime? DateEnd { get; set; }

    [Required(ErrorMessage = "Required")]
    public short ChoicesType { get; set; }

    [StringLength(500, ErrorMessage = "MaxLength")]
    public string TextAnswer { get; set; }

    public virtual List<SurveyChoiceDto> SurveyChoices { get; set; }
}

public class SurveyChoiceDto
{
    [Required(ErrorMessage = "Required")]
    public int? LanguageId { get; set; }

    [Required(ErrorMessage = "Required"),
    StringLength(200, ErrorMessage = "MaxLength")]
    public string Title { get; set; }

    public long ChoiceId { get; set; }
    public int SurveyQuesId { get; set; }
    public long Count { get; set; }
    public bool MarkedToDelete { get; set; }
    public bool IsSelected { get; set; }
}

My view :

@model List<SurveyQuestionDto>

@if (Model != null && Model.Count() > 0)
{
    <form action="@Url.Action("Answer", "Survey", new { typeId })" method="post"  enctype="multipart/form-data">
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)

        @foreach (var question in Model)
        {
            int i = 0;
            @Html.HiddenFor(m => m[i].SurveyQuesId, new { Value = question.SurveyQuesId })
            <div style="background:#cccccc; padding:20px; margin:20px;">
                <h2>@question.Title</h2>
                @if (question.ChoicesType == (int)ChoicesTypeEnum.Text)
                {
                    @Html.TextAreaFor(m => m[i].TextAnswer, new Dictionary<string, object> { { "data-val", "true" }, { "data-val-required", _loc["Required"] } })
                }
                else
                {
                    <ul style="list-style-type:none;">
                        @foreach (var choice in question.SurveyChoices)
                        {
                            int a = 0;
                            <li>
                                @Html.HiddenFor(m => m[i].SurveyChoices[a].ChoiceId, new { Value = choice.ChoiceId })
                                @if (question.ChoicesType == (int)ChoicesTypeEnum.SingleChoice)
                                {
                                    @Html.RadioButtonFor(m => m[i].SurveyChoices[a].IsSelected, null, new Dictionary<string, object> { { "data-val", "true" }, { "data-val-required", _loc["Required"] } })
                                }
                                else
                                {
                                    @Html.CheckBoxFor(m => m[i].SurveyChoices[a].IsSelected, new Dictionary<string, object> { { "data-val", "true" }, { "data-val-required", _loc["Required"] } })
                                }
                                <label>@choice.Title</label>
                            </li>
                            a  ;
                        }
                    </ul>
                }
            </div>
            i  ;
        }
        <button type="submit">Submit now</button>
    </form>
}

Model object already has its values:

public async Task<IActionResult> Index(int id)
{
    return View(await _rep.GetSurveyQuestionsWithChoices(id));
}

The problem starts with this line of code

 m[i].SurveyChoices[a].ChoiceId

Any ideas?

CodePudding user response:

you have a bug in your code

@foreach (var question in Model)
{
            int i = 0;
 @Html.HiddenFor(m => m[i].SurveyQuesId, new { Value = question.SurveyQuesId })

for each item you will always have i=0 since it repeats assigning zero.

it is much better to use for loop

@for(var i=0; i < Model.Count; i  )
{
 @Html.HiddenFor(m => m[i].SurveyQuesId, new { Value = @Model[i].SurveyQuesId })
....and so on

The same is for the second foreach loop in your code.Should be

@for (var a=0;  a < @Model[i].SurveyChoices.Count; a  )

CodePudding user response:

There are some mistakes in your code, variables i, a never change. you should handler this manually in your foreach loop like below:

@foreach (var question in Model)
{
   int i = 0;
   // rest of your code
   i  ;
}

or you can use a for loop instead of foreach:

for(int index=0;index<Model.Count;index  ){...}

Apart from theses, you can omit this if statement in your code because when there is no item, for loop does not run :

@if (Model != null && Model.Count() > 0)

or you can use Any() like below:

@if (Model.Any()){...}

bear in mind that you should return empty list if there is no data in you storage rather than null

  • Related