Wesley
Wesley

Reputation: 307

ViewModel assigned an object, how can I pass that back into the Post?

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>&nbsp;Create</button>
                <a href="@Url.Action("Index", "Assignment")" class="btn btn-primary"><i class="icon-back"></i>&nbsp;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

Answers (3)

Wesley
Wesley

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

Adam Tuliper
Adam Tuliper

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

Kirill Bestemyanov
Kirill Bestemyanov

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

Related Questions