My problem is quite common but I can't seem to figure out on my own why when I POST my model that it's null. My FormCollection seems to suggest it doesn't understand the whole model which it is POSTING. See code below:
My model - CaseForm.cs
namespace Models.CaseForm
{
public class CaseForm
{
public CaseForm()
{
this.Person = new Person();
this.Case = new Case();
this.Cases = new List<Case>();
}
public string strMessage;
public bool isValidModel;
public Person Person = new Person();
public Case Case = new Case();
public List<Case> Cases = new List<Case>();
}
}
My view = NewCase.cshtml
@model Models.CaseForm.CaseForm
@using (Html.BeginForm())
{
@Html.Raw(Model.strMessage)
<br />
@*@Html.HiddenFor(m => m.Case.CaseId)
@Html.HiddenFor(m => m.Case.CaseNotes)
@Html.HiddenFor(m => m.Case.CaseRef)
@Html.HiddenFor(m => m.Case.FirstAppointmentMade)
@Html.HiddenFor(m => m.Case.IsClosedRecord)
@Html.HiddenFor(m => m.Case.IsFirstContact)
@Html.HiddenFor(m => m.Case.PersonId)
@Html.HiddenFor(m => m.Case.ReasanForContact)
@Html.HiddenFor(m => m.Case.WasAdvisedByEmail)*@
<legend>
<fieldset>
<h4>New Case for @Html.Raw(Model.Person.Firstname + " " + Model.Person.Firstname)</h4>
</fieldset>
</legend>
<table>
<tr>
<td>@Html.LabelFor(m => m.Person.PersonRef)</td>
<td>@Html.DisplayFor(m => m.Person.PersonRef)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Person.LesasPerson.ActionTakenPending, "Action Taken Pending")</td>
<td>@Html.DisplayFor(m => m.Person.LesasPerson.ActionTakenPending)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Person.LesasPerson.DateArrivedInUk, "Date Arrived In UK")</td>
<td>@Html.DisplayFor(m => m.Person.LesasPerson.DateArrivedInUk)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Person.LesasPerson.ImmigrationStatus, "Immigration Status")</td>
@{
string ImmigrationStatus = Model.Person.LesasPerson.ImmigrationStatus == null ? "No status set for this person" : Model.Person.LesasPerson.ImmigrationStatus;
}
<td>@Html.Raw(ImmigrationStatus)</td>
</tr>
</table>
<br />
<div id="divCase" style="border-style: solid; border-width: thin; padding: 5px;">
<table>
<tr>
<td><b>If Case ref is not known then leave blank for now.</b></td>
</tr>
<tr>
<td>
@Html.LabelFor(m => m.Case.CaseRef, "Case Reference code")
</td>
<td>
@Html.TextBoxFor(m => m.Case.CaseRef)
</td>
</tr>
<tr>
<td>
@Html.LabelFor(m => m.Case.FirstAppointmentMade, "First Appointment Made")
</td>
<td>
@Html.TextBoxFor(m => m.Case.FirstAppointmentMade)
</td>
</tr>
<tr>
<td>
@Html.LabelFor(m => m.Case.IsFirstContact, "Is First Contact")
</td>
<td>
@Html.CheckBoxFor(m => m.Case.IsFirstContact)
</td>
</tr>
<tr>
<td>
@Html.LabelFor(m => m.Case.ReasanForContact, "Reason For Contact")
</td>
<td>
@{
List<SelectListItem> Reasons = new List<SelectListItem>();
Reasons.Add(new SelectListItem() { Text = "One Off Advice", Value = "One Off Advice", Selected = false });
Reasons.Add(new SelectListItem() { Text = "Housing", Value = "Housing", Selected = true });
Reasons.Add(new SelectListItem() { Text = "Immigration", Value = "Immigration", Selected = false });
Reasons.Add(new SelectListItem() { Text = "Social Advice", Value = "Social Advice", Selected = false });
Reasons.Add(new SelectListItem() { Text = "Legal", Value = "Legal", Selected = false });
Reasons = Reasons.OrderBy(r => r.Text).ToList();
}
@Html.DropDownListFor(m => m.Case.ReasanForContact, Reasons)
</td>
</tr>
<tr>
<td>
@Html.LabelFor(m => m.Case.WasAdvisedByEmail, "Was Advised By Email")
</td>
<td>
@Html.CheckBoxFor(m => m.Case.WasAdvisedByEmail)
</td>
</tr>
</table>
<hr />
<div id="divCaseNote" style="padding:10px;">
@for (int i = 0; i < Model.Case.CaseNotes.Count; i++)
{
int status = i + 1;
<table>
<tr>
<td>@Html.Label("This is note: " + status.ToString())</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Case.CaseNotes[i].CaseStatus, "Write title or status for note")</td>
<td>@Html.TextBoxFor(m => m.Case.CaseNotes[i].CaseStatus)</td>
<td>@Html.ValidationMessageFor(m => m.Case.CaseNotes[i].CaseStatus)</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Case.CaseNotes[i].CaseNote, "Case Note")</td>
<td>@Html.TextAreaFor(m => m.Case.CaseNotes[i].CaseNote)</td>
<td>@Html.ValidationMessageFor(m => m.Case.CaseNotes[i].CaseNote)</td>
@*@Html.HiddenFor(m => m.Case.CaseNotes[i].CaseDate)
@Html.HiddenFor(m => m.Case.CaseNotes[i].CaseId)
@Html.HiddenFor(m => m.Case.CaseNotes[i].CaseNote)
@Html.HiddenFor(m => m.Case.CaseNotes[i].CaseNoteId)
@Html.HiddenFor(m => m.Case.CaseNotes[i].CaseStatus)*@
</tr>
</table>
}
</div>
<input type="submit" value="Add Note For Case" name="btnSubmit" />
<input type="submit" value="Remove Note For Case" name="btnSubmit" />
</div>
<br />
<input type="submit" value="Save Case To Database" name="btnSubmit" />
<br />
<b>@Html.ActionLink("Go back to people grid", "PeopleDashboard")</b>
}
ActionResult NewCase (POST)
[HttpPost]
public ActionResult NewCase(string btnSubmit, FormCollection form, CaseForm Model)
{
RepositoryLesas RepositoryLesas = new RepositoryLesas();
switch (btnSubmit)
{
case "Add Note For Case":
#region AddClaimStatus
Model.Case.CaseNotes.Add(new CaseNotes());
// SET to false as Model is not ready for DB
Model.isValidModel = false;
// SET message for the user
Model.strMessage = "Type new note information in the fields below";
return View("~/Views/Case/NewCase.cshtml", Model);
#endregion
case "Remove Note For Case":
#region RemoveClaimStatus
// Can't remove IF only 1
Model.isValidModel = false;
if (Model.Case.CaseNotes.Count == 0 || Model.Case.CaseNotes.Count == 1)
{
Model.strMessage = "Must be at least one case note before saving case";
}
else
{
Model.Case.CaseNotes.RemoveAt(Model.Case.CaseNotes.Count - 1);
Model.strMessage = "One case note removed.";
}
return View("~/Views/Case/NewCase.cshtml", Model);
#endregion
//case "Save Case To Database":
//#region submit
//if (!Model.isValidModel)
//{
// RepositoryLesas.InsertClaim(Model);
// // Do one final check before going to success screen
// Model.strMessage = "Claim data inserted into the database.";
// Model.Person = RepositoryLesas.GetPerson(Model.Person.PersonID);
// // Use to persist data through redirect - Model data will be lost otherwise
// TempData["Model"] = Model;
// return RedirectToAction("Success", new { URL = SuccessClaimUrl });
//}
//else
//{
// Model.strMessage = "Claim data could not be inserted into the database. Missing key fields.";
// return View("~/Views/Claim/AddClaim.cshtml", Model);
//}
//#endregion
}
return View("~/Views/Case/NewCase.cshtml", Model);
}
My FormCollection
In my form collection, it only interprets the case object, it should show:
- strMessage
- isValidModel
- Case obj
- Cases collection
- Person obj
Why is this model not posting correctly?
You need getter and setter on your properties. The
DefaultModelBinder
creates a new instance ofCaseForm
but can set the values of its properties that have been posted back because they dont have setters.Note you do not need the parameter
FormCollection form
Note also your are rendering hidden inputs for some properties
and then creating a textbox for the same property
You need to remove the
HiddenFor
because it will only bind the first value on post back (the value in the hidden input) and ignore the second (the value in the textbox)