Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass list objects with MVC Razor

I am using an object but inside object I have a property that is a list of objects. I want to pass that object with the list objects inside it but the list is empty when I submit my form. I am not sure how to handle this.

Class

public class VSTAttendance
{
    public int MemberID { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public bool Attendant { get; set; }
}

public class ServiceAttendance 
{
    public int AttendanceID { get; set; }
    public int AttendanceTypeID { get; set; }
    public string AttendanceType { get; set; }
    public DateTime Service { get; set; }
    public int ServiceID { get; set; }
    public string Speaker { get; set; }
    public string Location { get; set; }
    public int HeadCount { get; set; }
    public int CategoryID { get; set; }
    public string Description { get; set; }
    public string ChurchNotes { get; set; }
    public string ServingNotes { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime CreatedBy { get; set; }
    public DateTime DateUpdate { get; set; }
    public DateTime UpdateBy { get; set; }
    public List<VSTAttendance> MemberAttendance { get; set; }


}

HTML

@using (Html.BeginForm("Attendance", "Home", FormMethod.Post, new { ReturnUrl = ViewBag.ReturnUrl, @class = "form-horizontal", role = "form" }))
{
    <div class="form-group">
        <label for="inputSpeaker" class="col-sm-2 control-label">
             Speaker</label>
        <div class="col-sm-6">
            @Html.TextBoxFor(m => m.Speaker, new { @class = "form-control", placeholder = "Speaker", type = "text", required = "required " })
        </div>
    </div>

<table class="table table-bordered table-condensed table-hover">
    <tr class="warning">
        <td></td>
        <td>Name</td>
        <td>Surname</td>
    </tr>
    @foreach (var item in Model.MemberAttendance)
    {
        <tr>
            <td>@Html.CheckBox("Attendant")</td>
            <td>@item.Name</td>
            <td>@item.Surname</td>
        </tr>
    }
    </table>

<div class="form-group">
    <div class="col-sm-10">
        <button type="submit" class="btn btn-info">
         <span class="glyphicon glyphicon-ok"></span>Submit</button>
     </div>
</div>

}
like image 562
Gericke Avatar asked May 08 '14 21:05

Gericke


3 Answers

You have to use for instead of foreach and use Hidden for . I have tested the following and works perfect

 @model ServiceAttendance

@{
    ViewBag.Title = "Attendance";
}

<h2>Attendance</h2>

@using (Html.BeginForm())
{
    <div class="form-group">
        <label for="inputSpeaker" class="col-sm-2 control-label">
            Speaker
        </label>
        <div class="col-sm-6">
            @Html.TextBoxFor(modelItem => modelItem.Speaker)
        </div>
    </div>

    <table class="table table-bordered table-condensed table-hover">
        <tr class="warning">
            <td></td>
            <td>Name</td>
            <td>Surname</td>
        </tr>
        @for (int i=0;i<Model.MemberAttendance.Count ;i++)
        {
            <tr>
                <td>@Html.CheckBoxFor(it=>Model.MemberAttendance[i].Attendant)
                   @Html.HiddenFor(it => Model.MemberAttendance[i].Attendant)
                </td>
                <td>@Model.MemberAttendance[i].Name
                    @Html.HiddenFor(it => Model.MemberAttendance[i].Name)</td>
                <td>@Model.MemberAttendance[i].Surname
                    @Html.HiddenFor(it=>Model.MemberAttendance[i].Surname)</td>
            </tr>
        }
    </table>

    <div class="form-group">
        <div class="col-sm-10">
            <button type="submit" class="btn btn-info">
                <span class="glyphicon glyphicon-ok"></span>Submit
            </button>
        </div>
    </div>

}

So what you have to do is replace the foreach with the following

 @for (int i=0;i<Model.MemberAttendance.Count ;i++)
            {
                <tr>
                    <td>@Html.CheckBoxFor(it=>Model.MemberAttendance[i].Attendant)
                       @Html.HiddenFor(it => Model.MemberAttendance[i].Attendant)
                    </td>
                    <td>@Model.MemberAttendance[i].Name
                        @Html.HiddenFor(it => Model.MemberAttendance[i].Name)</td>
                    <td>@Model.MemberAttendance[i].Surname
                        @Html.HiddenFor(it=>Model.MemberAttendance[i].Surname)</td>
                </tr>
            }
like image 70
Dan Hunex Avatar answered Oct 21 '22 03:10

Dan Hunex


Check out the BeginCollectionItem html helper available on nuget or here: https://github.com/danludwig/BeginCollectionItem

You can see more information on the behavior on this blog: http://weblogs.asp.net/nmarun/archive/2010/03/13/asp-net-mvc-2-model-binding-for-a-collection.aspx

The default model binder is expecting the names to come in this form:

MemberAttendance[0].Prop = "prop"
MemberAttendance[0].BoolProp = false

so you need to name the inputs similarly:

<input type="checkbox" name="MemberAttendance[0].Attendant" />
<input type="hidden" name="MemberAttendance[0].Name" value="Nick" />
<input type="hidden" name="MemberAttendance[0].MemberId" value="1" /> <!-- the hiddens are to maintain state of the rest of the properties -->

<input type="checkbox" name="MemberAttendance[1].Attendant" />
<input type="hidden" name="MemberAttendance[1].Name" value="Someone else" />
<input type="hidden" name="MemberAttendance[1].MemberId" value="2" />
like image 39
Nick Spiers Avatar answered Oct 21 '22 03:10

Nick Spiers


You did not output any part of MemberAttendance to post back. You just output its contents.

Minimal changes to your code would be to change the foreach:

@for (int i=0; i<Model.MemberAttendance.Count; i++)
{
    ...your current html

    @Html.HiddenFor(m => m.MemberAttendance[i].MemberID);
    @Html.HiddenFor(m => m.MemberAttendance[i].Name);
    @Html.HiddenFor(m => m.MemberAttendance[i].Surname);
    @Html.HiddenFor(m => m.MemberAttendance[i].Attendant);
}

IF that is what you really want to do.

like image 43
Agent Shark Avatar answered Oct 21 '22 03:10

Agent Shark