1

I have a model like this:

public class TRViewModel
{
    public List<TR> TRecord { get; set; }
}

[Table("TRecord")]
public partial class TRecord
{
    [Key]
    [DisplayName("TID")]
    public int Tid { get; set; }
    public String Tname { get; set; }
}

The controller is like this:

    public ActionResult Audit(int? id)
    {
        var tQ = from t in db.TRecordDBSet
                        select t;

        var list = tQ.ToList();
        return View(list);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Audit(List<TRecord> list)
    {
        if (ModelState.IsValid)
        {
            db.Entry(list).State = System.Data.Entity.EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Audit");
        }
        return View(list);
    }

The view is like this:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Tid)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Tname)
        </th>
    </tr>
    @foreach (var item in Model)
    {
            <tr>
                    <td>
                            @Html.DisplayFor(modelItem => item.Tid)
                    </td>
                    <td>
                            @Html.EditFor(modelItem => item.Tname)
                    </td>
            </tr>
    }

<div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
</div>

I want to pass the list to the controller to save the new variable to the database but when debugging I found the list is null, what is going wrong?

d219
  • 2,707
  • 5
  • 31
  • 36
Keon Vong
  • 85
  • 8
  • 2
    Take a look at what is in your html. I suppose that all of your inputs from the collection have the same name. To bind multiple items into a collection you have to have them indexed with [1..n]. – sephirot Mar 16 '17 at 07:46
  • 2
    Try changing `foreach` to simple `for` loop and use index array for each model, e.g.: `@for (int i = 0; i < Model.Count; i++) { Html.DisplayFor(item => item[i].Tid); Html.EditFor(modelItem => item[i].Tname) }`, or using more organized way by creating editor template with `EditorForModel`. – Tetsuya Yamamoto Mar 16 '17 at 07:51
  • 1
    I think this link will be helpful for you. [how to pass list to controller](http://stackoverflow.com/questions/12888248/submit-a-list-from-view-to-controller) – Numan KIZILIRMAK Mar 16 '17 at 08:04

1 Answers1

3

Assuming you have IEnumerable<TRecord> as model bound to view, you can change foreach loop to for loop with index array of every properties inside model and set binding type to IList to match with controller input parameter:

@model IList<TRecord>

@using (Html.BeginForm())
{
    // display names area

    @for (var i = 0; i < Model.Count; i++)
    {
        <tr>
            <td>
                @Html.DisplayFor(item => item[i].Tid)
            </td>
            <td>
                @Html.EditFor(item => item[i].Tname)
            </td>
        </tr>
    }

    // submit button area
}

The other way to post IEnumerable collection is creating editor template and put HTML helpers inside it, then use EditorForModel (see Darin Dimitrov's approach here).

Similar issues:

How to pass IEnumerable list to controller in MVC including checkbox state?

MVC passing IEnumerable<CustomVM> to Controller

Pass IEnumerable list to controller

Community
  • 1
  • 1
Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61
  • Thank you !!!! @Tetsuya Yamamoto – Keon Vong Mar 17 '17 at 01:34
  • Thank you!!! Successed to save the list @for (var i = 0; i < Model.Count; i++) { @Html.DisplayFor(item => item[i].Tid) @Html.EditorFor(item => item[i].Tname) I found that I must use EditorFor, that the values will pass to the list, it I use DisplayFor, the variable return to the list will changes to "null", how can I pass an original data to the controller without using EditorFor? – Keon Vong Mar 17 '17 at 01:41
  • You can use `@Html.TextBoxFor(item => item[i].Tid, new { @readonly = "readonly" })`. Note that `EditorFor` renders HTML input element depending on data type defined on model, and tid values should be passed as list input parameter. – Tetsuya Yamamoto Mar 17 '17 at 02:22
  • that works and i don't want the box ..... – Keon Vong Mar 17 '17 at 02:25
  • only want the value to display – Keon Vong Mar 17 '17 at 02:25
  • Since you only want to show value on `TextBoxFor`, use CSS style including `border: 0 none transparent`, e.g. `@Html.TextBoxFor(item => item[i].Tid, new { @readonly = "readonly", @style = "border: 0 none transparent;" })` – Tetsuya Yamamoto Mar 17 '17 at 02:30
  • may i shorten the width of the textbox? – Keon Vong Mar 17 '17 at 02:55
  • Of course. Just add CSS width attribute by `new { @readonly = "readonly", @style = "border: 0 none transparent; width:[textbox size]" }`, or simply use a CSS class with `new { @readonly = "readonly", @class = "[class name]" }` then putting all CSS selectors together inside that class. – Tetsuya Yamamoto Mar 17 '17 at 02:58