0

I am trying to post a list of objects from View to controller.

Below is my code:

View :

    @using Models
    @model IList<Add>
    @{
        ViewData["Title"] = "AddNewFields";
    }
    <form asp-controller="Trans" asp-action="InsertFields" method="post" class="form-horizontal card-body" role="form">
<td><input type="text" class="form-control" value="Field Size" asp-for="@Model[i].TypeFlag"/></td>
                            <td><input type="text" class="form-control" value="Field Value" asp-for="@Model[i].FieldValue"/></td>
                            <td><input type="text" class="form-control" value="Field Format" asp-for="@Model[i].FieldFormat"/></td>
</form>  

I will be adding mo these text fields again on button click.

Model:

public class Add
    {        
        public string TypeFlag { get; set; }

        public string FieldValue { get; set; }

        public string FieldFormat { get; set; }
    }

Controller:

public string InsertFields(IList<Add> fields)
{
            //some logic
}

When I run the application, I am getting the below error:

NullReferenceException: Object reference not set to an instance of an object.

    AspNetCore.Views_Trans_Add.<ExecuteAsync>b__27_0() in AddNewFields.cshtml

            @for (int i = 0; i < Model.Count; i++)

Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
Microsoft.AspNetCore.Mvc.TagHelpers.RenderAtEndOfFormTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.RunAsync(TagHelperExecutionContext executionContext)

Please help me...I am stuck here from 2 days..

K K
  • 1
  • 1
  • @lgor @ Stephen, it's not duplicate. his problem is very clear: html fields does not match required parameter. – Dongdong Aug 10 '18 at 12:54
  • @lgor @ Stephen, This is not duplicate...please read the question again – K K Aug 10 '18 at 14:55

1 Answers1

0

2 issues:

  1. Model is null
  2. Action will not get values.

solution:

Your HTML should be this style

@{
    var fields = (Model ?? Enumerable.Empty<Add>()).ToList(); //this variable must be same with the parameter in action.
}

<form asp-action="Test" method="post">
    <table class="table">
        <tbody>
            <tr>
                <td>
                    <div class="form-group">
                        <input type="submit" value="Submit" />
                    </div>
                </td>
            </tr>
            @for (var i = 0; i < fields.Count; i++) //you must use for, not foreach
            {
                <tr>
                    <td>
                        <div class="form-group">
                            <input type="hidden" asp-for="@fields[i].Id" />
                            <input asp-for="@fields[i].Name" class="form-control" />
                        </div>
                    </td>
                </tr>
            }
        </tbody>
    </table>
</form>

your controller should be this:

    [HttpPost]
    public async Task<IActionResult> Test(IEnumerable<Add> fields)
    //be aware: the parameter name "fields" must be same with your html
    //the type should be "IEnumerable<Add>", more compatible with different versions of MVC
    {
        .....your logic
        return Json(new { ... });
    }

the generated html is this style:

 <tr>
    <td>
        <div class="form-group">
            <input type="hidden" id="fields_0__Id" name="fields[0].Id" value="14">
            <input class="form-control" type="text" id="fields_0__Name" name="fields[0].Name" value="xxxxx">
        </div>
    </td>
</tr>
<tr>
    <td>
        <div class="form-group">
            <input type="hidden" id="fields_1__Id" name="fields[1].Id" value="1">
            <input class="form-control" type="text" id="fields_1__Name" name="fields[1].Name" value="xxxx">
        </div>
    </td>
</tr>

you will see the reason: the parameter fields is just a field of html form, they must match each other.

Dongdong
  • 2,208
  • 19
  • 28
  • @for (var i = 0; i < fields.Count; i++) here..fiels value is 0..and its not entering for loop and not creating text box elements – K K Aug 10 '18 at 15:01
  • yep. if you want to dynamically create new row for your form, it's another thing, not in this question. but it's pretty simple. you can render html by jquery or ajaxrequest, I prefer html. just follow the generated html template to append a new table row `tr`, that's all. – Dongdong Aug 10 '18 at 18:29