I was having a weird issue with a very simple model. When posted back to the controller, the model was always null. Not being able to find the issue, I pulled it apart rebuilt the model, adding an accessor at a time.
I finally discovered that having a string accessor called “State” and using it in a view was causing the issue:
<%= Html.HiddenFor(m => m.State) %>
Why would this happen?
Here is the model:
public class StudentSelectState
{
public string State { get; set; }
public int SelectedYear { get; set; }
public IDictionary<string, string> Years { get; set; }
}
Here is the controller:
[HttpGet]
public ActionResult SelectStudent()
{
var StudentYears = absenceServices.GetStudentYears();
var state = new StudentSelectState {Years = Lists.StudentYearListToDictionary(StudentYears)};
return View(state);
}
[HttpPost]
public ActionResult SelectStudent(StudentSelectState state)
{
var StudentYears = absenceServices.GetStudentYears();
state.Years = Lists.StudentYearListToDictionary(StudentYears);
return View(state);
}
and here is the view:
<% using (Html.BeginForm())
{%>
<%= Html.ValidationSummary() %>
<%= Html.TextBoxFor(m => m.State) %>
<%= Html.RadioButtonListFor(m => m.SelectedYear, Model.Years, "StudentYears") %>
<div style="clear: both;">
<input value="submit" />
</div>
<% } %>
The RadioButtonListFor is a HtmlHelper I wrote to populate RadioButtonLists.
I am using Ninject 2.0 to inject services into the contructor, but I don’t think this has a bearing on this issue.
I could rename the accessor, but I’m curious as to why this is happening.
You could also rename the argument of your POST action.
When you POST the form the following is sent in the request:
Now the default model binder sees that your action argument is called state and it tries to bind the
abcdvalue to it which obviously fails because thestatevariable is not a string. So be careful when naming your view model properties.To avoid those kind of conflicts I prefer to name my action arguments
modelorviewModel.Yet another possibility if you don’t want to rename anything is to use the
[BindPrefix]attribute, like so: