Reputation: 307
So I have two methods:
public ActionResult Create(Guid id)
{
Assignment viewModel = new Assignment();
viewModel.Classroom = classroomRepository.GetByID(id);
return View(viewModel);
}
[HttpPost]
public ActionResult Create(Assignment assignment)
{
if (ModelState.IsValid)
{
assignmentRepository.Insert(assignment);
assignmentRepository.Save();
return RedirectToAction("Index");
}
return View(assignment);
}
As you can see, when I load up my Create page, I'm loading a Classroom into the viewModel. This works and displays the correct Classroom on the View.
My problem occurs when I POST to the Create method, my assignment
object I pass in now doesn't include (it's NULL) Classroom that I passed in on GET.
EDIT ~ To Show View:
@model My_School_Book.Models.Assignment
@{
ViewBag.Title = "Create";
}
<div class="span9">
<div class="row-fluid">
<h1>Creating New Assignment:</h1>
<hr />
@using (Html.BeginForm("Create", "Assignment", FormMethod.Post, new { @class = "form-horizontal" }))
{
@Html.ValidationSummary(true)
<div class="control-group">
@Html.LabelFor(model => model.Classroom.Name, "Classroom", new { @class = "control-label" })
<div class="controls">
<span style="font-size: 26px;">@Html.DisplayTextFor(model => model.Classroom.Name)</span>
</div>
</div>
<div class="control-group">
@Html.LabelFor(model => model.Name, new { @class = "control-label" })
<div class="controls">
@Html.TextBoxFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="control-group">
@Html.LabelFor(model => model.Description, new { @class = "control-label" })
<div class="controls">
@Html.TextAreaFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
</div>
<div class="control-group">
@Html.LabelFor(model => model.AssignedDate, new { @class = "control-label" })
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-calendar"></i></span>@Html.TextBoxFor(model => model.AssignedDate)
</div>
@Html.ValidationMessageFor(model => model.AssignedDate)
</div>
</div>
<div class="control-group">
@Html.LabelFor(model => model.DueDate, new { @class = "control-label" })
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-calendar"></i></span>@Html.TextBoxFor(model => model.DueDate)
</div>
@Html.ValidationMessageFor(model => model.DueDate)
</div>
</div>
<div class="control-group">
@Html.LabelFor(model => model.Weight, new { @class = "control-label" })
<div class="controls">
@Html.TextBoxFor(model => model.Weight, new { @class = "span2" })
@Html.ValidationMessageFor(model => model.Weight)
</div>
</div>
<div class="control-group">
@Html.LabelFor(model => model.Total, new { @class = "control-label" })
<div class="controls">
@Html.TextBoxFor(model => model.Total, new { @class = "span2" })
@Html.ValidationMessageFor(model => model.Total)
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary"><i class="icon-plus-6"></i> Create</button>
<a href="@Url.Action("Index", "Assignment")" class="btn btn-primary"><i class="icon-back"></i> Cancel</a>
</div>
}
</div>
</div>
@section Scripts
{
<script type="text/javascript">
$(function () {
$("#AssignedDate").datepicker({
showOtherMonths: true,
selectOtherMonths: true,
dateFormat: "DD MM d, yy",
minDate: -14,
onSelect: function (selectedDate) {
$("#DueDate").datepicker("option", "minDate", selectedDate);
}
});
$("#DueDate").datepicker({
dateFormat: "DD MM d, yy",
minDate: 0,
onSelect: function (selectedDate) {
$("#AssignedDate").datepicker("option", "maxDate", selectedDate);
}
});
});
</script>
}
Upvotes: 0
Views: 227
Reputation: 307
I ended up using a View Model:
public class AssignmentCreateData
{
public Guid ClassroomID { get; set; }
public String ClassroomName { get; set; }
public Assignment Assignment { get; set; }
}
and my controller looked like this:
public ActionResult Create(Guid id)
{
AssignmentCreateData viewModel = new AssignmentCreateData();
Classroom classroom = classroomRepository.GetByID(id);
viewModel.ClassroomID = classroom.ClassroomID;
viewModel.ClassroomName = classroom.Name;
viewModel.Assignment = null;
return View(viewModel);
}
[HttpPost]
public ActionResult Create(AssignmentCreateData viewModel)
{
if (ModelState.IsValid)
{
viewModel.Assignment.ClassroomID = viewModel.ClassroomID;
assignmentRepository.Insert(viewModel.Assignment);
assignmentRepository.Save();
return RedirectToAction("Index");
}
return View(viewModel);
}
Then my View includes:
@Html.HiddenFor(model => model.ClassroomID)
Upvotes: 0
Reputation: 30152
You are only including Classroom.Name, thus on the form post nothing is there for the model binder to populate your model with.
Do you really need the classroom populated back though? What are you trying to accomplish? If you need the ID simply write it out as:
@Html.HiddenFor(o=>o.Classroom.ClassroomId)
(or whatever the id is) and load it back up on the server side.
If you really need it there - you can write it out as inputs via
@Html.EditorFor(o=>o.Classroom)
That then allows the end user to modify it which I dont think you want, thus I'd use the ID (guid).
Upvotes: 2
Reputation: 11964
If you want that Classroom survive post then you need to add it to form in hiddenfield:
Just add this into form:
@Html.HiddenFor(m=m.Classroom.ClassroomId)
@Html.HiddenFor(m=m.Classroom.ClassroomName)
Upvotes: 0