Reputation: 2069
I am trying to pass a complex data structure from Controller to View and Back to Controller which contains Lists. I can see the list items in View. I want to edit those and send it back to the controller. I am able to edit some properties but for lists, I am getting null value in the controller.
Here is an example (simulation) of what I am trying to achieve:
Consider Model -
using System.Collections.Generic;
namespace WebApplication1.Models
{
public class StudentViewModel
{
public string StudentId { get; set; }
public string FeedBack { get; set; }
public List<ScoreCard> ScoreCards;
}
public class ScoreCard
{
public string Subject { get; set; }
public string Marks { get; set; }
}
}
Controller -
public class StudentController : Controller
{
public ActionResult Index()
{
var model = new StudentViewModel();
model.StudentId = "Some Student";
model.ScoreCards = new List<ScoreCard>
{
new ScoreCard()
{
Marks = "0",
Subject = "English"
},
new ScoreCard()
{
Marks = "0",
Subject = "Maths"
}
};
return View("View", model);
}
public ActionResult SubmitScore(StudentViewModel model)
{
/* Some Code */
}
}
View -
@model WebApplication1.Models.StudentViewModel
@{
ViewBag.Title = "Title";
}
@using (Html.BeginForm("SubmitScore", "Student", FormMethod.Post))
{
@Html.DisplayName(@Model.StudentId)<br />
<label>Comment:</label><br/>
@Html.EditorFor(m => m.FeedBack, new { htmlAttributes = new { @type = "text", id = @Model.FeedBack} })<br />
for (var i = 0; i < @Model.ScoreCards.Count; i++)
{
@Html.DisplayName(@Model.ScoreCards[i].Subject) <br/>
@Html.EditorFor(m => m.ScoreCards[i].Marks, new { htmlAttributes = new { @type = "number", @min = 0, id = @Model.ScoreCards[i].Marks} })<br />
}
<input class="btn btn-primary" type="submit" value="Submit" />
}
When I run the application -
When I click submit, I am able to see model.FeedBack
but the list is set to null.
Something similar is achieved in this question & it's answer; I am not sure what exactly I am missing here.
Upvotes: 2
Views: 3489
Reputation: 247581
you send no input for the Subject
. You'll need a hidden input for that along with any other value you want returned to the controller when the form is posted. Also a simple text box should work for the marks.
@using (Html.BeginForm("SubmitScore", "Student", FormMethod.Post))
{
@Html.DisplayName(@Model.StudentId)<br />
@Html.HiddenFor(m => m.StudentId)
<label>Comment:</label><br/>
@Html.EditorFor(m => m.FeedBack, new { htmlAttributes = new { @type = "text", id = @Model.FeedBack} })<br />
for (var i = 0; i < @Model.ScoreCards.Count; i++) {
@Html.HiddenFor(m => m.ScoreCards[i].Subject)
@Html.DisplayName(@Model.ScoreCards[i].Subject) <br/>
@Html.TextBoxFor(m => m.ScoreCards[i].Marks, new { htmlAttributes = new { @type = "number", @min = 0} })<br />
}
<input class="btn btn-primary" type="submit" value="Submit" />
}
Finally you need to use properties in order for the model binding to work. You currently have ScoreCards
as a field so update it to a property.
public class StudentViewModel {
public string StudentId { get; set; }
public string FeedBack { get; set; }
public List<ScoreCard> ScoreCards { get; set; }
}
Upvotes: 2