Hello and thank you for any feedback you give. I've made a partial view very much like a working one I already have, yet the view returns a null model. I've checked the output window and it says there is an invalid operation exception being thrown every time the submit button is being clicked.
"A first chance exception of type ;System.InvalidOperationException' occurred in System.Web.Mvc.dll"
In the output window I am also seeing binding exceptions, yet I can't find a single thing I'm doing wrong.
Here is my controller:
public class CreateProjectController
{
//...other code omitted for brevity
[HttpGet]
public ActionResult CreatePlatform()
{
var workitem = storeWrapper.GetNewWorkItem("Platform");
var targetPlatformViewModel = new TargetPlatformViewModel() { CurrentUserCanCreate = true, CurrentUserCanWrite = true };
// set properties
targetPlatformViewModel.Initialize(workitem);
return PartialView(targetPlatformViewModel);
}
[HttpPost]
public ActionResult CreatePlatform(TargetPlatformViewModel platform)
{
//======< the parameter above is null for some reason >======//
return PartialView(platform);
}
}
Here is my partial view:
@model Website.UI.Models.TargetPlatformViewModel
@using (Ajax.BeginForm("CreatePlatform", "CreateProject", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "platformView" }))
{
@Html.HiddenFor(model => model.ID)
@Html.HiddenFor(model => model.Title)
@Html.HiddenFor(model => model.ProjectId)
@Html.HiddenFor(model => model.ProjectTitle)
<table>
<tr>
<td>@Html.LabelFor(model => model.Platform)</td>
<td>
@{
var platformList = new List<SelectListItem>();
foreach (var allowedValue in Model.PlatformTypes)
{
platformList.Add(new SelectListItem() { Text = allowedValue, Value = allowedValue, Selected = false });
}
}
@Html.DropDownListFor(model => model.Platform, platformList)
</td>
<td>@Html.ValidationMessage("Platform")</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.Distribution)</td>
<td>
@{ var distributionList = new List<SelectListItem>(); }
@foreach (var allowedValue in Model.DistributionTypes)
{
distributionList.Add(new SelectListItem() { Text = allowedValue, Value = allowedValue, Selected = false });
}
@Html.DropDownListFor(model => model.Distribution, distributionList)
</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.MaxLocalPlayers)</td>
<td>@Html.TextBoxFor(model => model.MaxLocalPlayers)</td>
<td>@Html.ValidationMessage("MaxLocalPlayers")</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.MaxOnlinePlayers)</td>
<td>@Html.TextBoxFor(model => model.MaxOnlinePlayers)</td>
<td>@Html.ValidationMessage("MaxOnlinePlayers")</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.OperatingSystems)</td>
<td>
@foreach (var os in Model.OperatingSystems)
{
<input name="osCheckbox" style="margin-right: 5px; margin-left: 10px;" type="checkbox" data-osname="@os.Key"
data-val-required="The osCheckbox Value field is required." checked=@os.Value>
@os.Key
<br />
}
</td>
<td>@Html.HiddenFor(model => model.SelectedOperatingSystems, new { @id = "SelectedOperatingSystems" })</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.KinectEnabled)</td>
<td>
@{ var kinectEnabled = Model.KinectEnabled == null ? false : Model.KinectEnabled.Value; }
<input type="checkbox" checked=@kinectEnabled />
</td>
</tr>
</table>
<input type="submit" value="Save"/>
}
<script type="text/javascript">
$(function () {
$('#submitTargetPlatform').click(function (e) {
var checkVals = [];
$("input[name='osCheckbox']").each(function (i) {
if (this.checked) {
checkVals[i] = $(this).data("osname");
}
});
var names = "";
for (var i = 0; i < checkVals.length; i++) {
if (checkVals[i] != null && checkVals[i] != "") {
names += checkVals[i]
if (i != checkVals.length - 1) {
names += ";";
}
}
}
$('#SelectedOperatingSystems').val(names);
});
});
</script>
My model has only properties for everything and uses an Initialize method to set them.
public class TargetPlatformViewModel
{
#region Properties
public bool CurrentUserCanWrite { get; set; }
public bool CurrentUserCanCreate { get; set; }
public int ID { get; set; }
[Required()]
public string Platform { get; set; }
public List<string> PlatformTypes { get; set; }
public string Title { get; set; }
[Range(0.00, int.MaxValue, ErrorMessage = "Please enter a positive number.")]
[Display(Name = "Max Local Players")]
public int? MaxLocalPlayers { get; set; }
[Range(0.00, int.MaxValue, ErrorMessage = "Please enter a positive number.")]
[Display(Name = "Max Online Players")]
public int? MaxOnlinePlayers { get; set; }
public string Distribution { get; set; }
public List<string> DistributionTypes { get; set; }
[Display(Name = "Operating Systems")]
public Dictionary<string, bool> OperatingSystems { get; set; }
public string SelectedOperatingSystems { get; set; }
public bool? KinectEnabled { get; set; }
public string ProjectTitle { get; set; }
public int ProjectId { get; set; }
#endregion Properties
public TargetPlatformViewModel()
{
OperatingSystems = new Dictionary<string, bool>();
}
public void Initialize(IWorkItemData workitem)
{
var wi = workitem as TFSWorkItemData;
ID = wi.ID != null ? wi.ID.Value : 0;
Platform = wi[FieldName].Value.ToString();
PlatformTypes = wi.GetAllowedValues(FieldName);
Title = wi[FieldName].Value.ToString();
MaxLocalPlayers = (int?)wi[FieldName].Value;
MaxOnlinePlayers = (int?)wi[FieldName].Value;
Distribution = wi[FieldName].Value.ToString();
DistributionTypes = wi.GetAllowedValues(FieldName);
var ke = workitem[FieldName].Value;
if (string.IsNullOrEmpty(ke as string))
KinectEnabled = null;
else
KinectEnabled = ke.ToString() == "Yes";
createOSDictionary(wi);
ProjectTitle = wi[FieldName].Value.ToString();
var parentLink = wi.Links.SingleOrDefault(l => l.LinkType == WorkItemLinkRelationshipType.Parent);
if (parentLink != null)
ProjectId = parentLink.TargetID;
}
private void createOSDictionary(TFSWorkItemData workitem)
{
var osList = workitem.GetAllowedValues(FieldName);
SelectedOperatingSystems = workitem[FieldName].Value as string;
var splitList = string.IsNullOrEmpty(SelectedOperatingSystems) ? null : SelectedOperatingSystems.Split(';');
foreach (var os in osList)
{
if (splitList != null)
OperatingSystems.Add(os, splitList.Contains(os));
else
OperatingSystems.Add(os, false);
}
}
}
Another thing that isn't going right is that when the save/submit button is clicked, no validation messages appear.
Here is what the header of my _Layout file looks like:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Blah</title>
@Styles.Render("~/Content/css")
<link href="~/Content/ErrorStyles.css" rel="stylesheet"/>
<link href="~/Content/CustomStyles.css" rel="stylesheet"/>
@Scripts.Render("~/bundles/jquery")
<script src="~/Scripts/jquery-2.1.4.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="~/Scripts/jquery-ui-1.11.4.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/bootstrap")
</head>
So I need help with why my model is being returned null by the view in the POST method of my controller. Thank you.