0

View:

@model MyApp.Models.Activity

@using (Html.BeginForm("Activity_Details", "Activity", FormMethod.Post))
{
    @Html.ValidationSummary(true)
    @Html.AntiForgeryToken()

    @Html.HiddenFor(model => model.ActivityName)
    @Html.HiddenFor(model => model.ActDate)
    @Html.HiddenFor(model => model.DateAccomplished)

    @Html.HiddenFor(model => model.Participants)

    <div class="body-header">
       <div>
            <h2>Activity Information</h2>
       </div>
       <br />
        <div class="buttons">
            <input type="submit" name="submitButton" value="Save" class="button save icon" />
            <a class="button" href="@Url.Action("Activity_List", "Activity")"><span class="back icon"></span>Back</a>
        </div>
    </div>
    <br />
    <div class="content-wrapper">
       <div class="sub-content">
            <div class="item">
                <span>@Html.DisplayNameFor(model => model.ActivityName)</span>
                @Html.DisplayFor(model => model.ActivityName)
            </div>
            <div class="item">
                <span>@Html.DisplayNameFor(model => model.ActDate)</span>
                @Html.DisplayFor(model => model.ActDate)
            </div>
            <div class="item">
                <span>@Html.DisplayNameFor(model => model.DateAccomplished)</span>
                @Html.DisplayFor(model => model.DateAccomplished)
            </div>
       </div>
       <div class="sub-content">
            <table cellspacing="0">
                <thead>
                    <tr>
                        <th>Last Name</th>
                        <th>First Name</th>
                        <th>Actual Amount</th>
                    </tr>
                </thead>
                <tbody>
                @foreach (var item in Model.Participants)
                {
                    <tr>
                        <td>@item.LastName</td>
                        <td>@item.FirstName</td>
                        <td>@item.Amount</td>
                    </tr>
                }
                </tbody>
            </table>
        </div>
    </div>
}

Controller:

[HttpPost()]
public ActionResult Activity_Details(string submitButton, Activity model)
{
    //AFTER CLICKING THE SUBMIT BUTTON
    //model.Participants doesnt retained its values
    return View(model);
}

public class Activity
{
    public string ActivityName { get; set; }
    public DateTime ActDate { get; set; }
    public DateTime DateAccomplished { get; set; }

    public virtual IEnumerable<Participant> Participants { get; set; }
}

public class Participant
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Amount { get; set; }
}

I have these Models Activity and Participant which will be displayed in one view and the Participant Model will iterate to create a table.

My Problem now is I need to Update the "Amount" per participants after clicking the submit button and whats happening right now is that when the Model is passed back to ActionResult...Participants model is null and only the Activity Model has data.

ekad
  • 14,436
  • 26
  • 44
  • 46
user3035024
  • 199
  • 2
  • 5
  • 17

2 Answers2

0

What you need is something called list binding. This:

 @foreach (var item in Model.Participants)
 {
     <tr>
          <td>@item.LastName</td>
          <td>@item.FirstName</td>
          <td>@item.Amount</td>
      </tr>
  }

Is not sending back any data. Try:

@for( int i = 0; i < Model.Participants.Count(); ++i)
{
    @Html.HiddenFor(m => m.Participants[i].LastName)
    @Html.HiddenFor(m => m.Participants[i].FirstName)
    @Html.HiddenFor(m => m.Participants[i].Amount)
}

Make sure i is sequential and in incremental order and the default binder will be happy to pick it up.

There are other methods you can apply, but this is the easiest.

beautifulcoder
  • 10,832
  • 3
  • 19
  • 29
  • I used your solution but instead of m.Participants[i] I used modelItem.TargetMDs.ElementAt(i) but still after submit...Model.Participants was null. – user3035024 Feb 13 '15 at 03:05
  • @user3035024 - So, what you're saying is that you did what was suggested, except you did something totally different than what was suggested, and you don't understand why doing something totally different didn't work? – Erik Funkenbusch Feb 13 '15 at 06:04
  • Because **Indexing** is not applicable to **IEnumerable** – user3035024 Feb 13 '15 at 06:12
0

There are a lot of things wrong here. First, you cannot model bind to an IEnumerable, since the model binder will have no idea what kind of actual object to instantiate to back it. Use a List<Participant> or Collection<Participant>.

Second, You cannot use a HiddenFor with a collection or IEnumerable. You can only put a single discreet type there. You need to write each Participant in the list to a separate HiddenFor(). This is probably pointless anyways, as in most cases you have this information on the server anyways so there is no reason to post it back to the server. Particularly here, where you're DISPLAYING data, and not updating it...

You only need to post data back if the user can change it, or select it (in which case you are only posting the selection mechanism, such as Id)

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291