0

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.

L_Laxton
  • 67
  • 1
  • 7
  • For a start `foreach (var allowedValue in Model.PlatformTypes)` will throw an exception because `PlatformTypes` is `null` –  Feb 10 '16 at 01:21
  • You need to rethink everything your doing here. A view model should be just that - containing only properties, not methods. Your controller should be responsible for populating the data in it. –  Feb 10 '16 at 01:23
  • PlatformTypes is set in the Initialize method. It is called in the get method in the controller. – L_Laxton Feb 10 '16 at 01:24
  • Is it. Where in your POST method do you call that before returning the view! –  Feb 10 '16 at 01:25
  • The view is returning null. What happens in the POST method is not relevant to that. I have a break point in the POST method, I check the parameter for the view model and it is null. I'm assuming there is a binding issue. - I apologize for not making that clearer in my question. – L_Laxton Feb 10 '16 at 01:27
  • That's because the parameter in your POST method is named `platform` and you also have a property in your model named `platform` (change the method parameter name to (say) `TargetPlatformViewModel model`). But that will only solve that issue. Sorry to be harsh, but there is so much bad coding here I would be surprised if anything ever works. –  Feb 10 '16 at 01:32

0 Answers0