Knockout.js & list of checkboxes: post to mvc controller
asp.net-mvc, asp.net-mvc-2, asp.net-mvc-3, knockout-mapping-plugin, knockout.js
Solution
You cant use $.post you need to go for the underlying $.ajax and add the correct contenttype to make mvc accept the posted json and do the model binding (contenttype should be "application/json; charset=utf-8") google for it and you will se lots of examples
Problem
I have an MVC view model that looks like this: ``` public class DirectorySearchModel { [Display(Name = "First name contains")] public string FirstName { get; set; } [Display(Name = "Last name contains")] public string LastName { get; set; } public CountriesCollection Countries { get; set; } public IEnumerable<Country> SelectedCountries { get; set; } public IEnumerable<Country> AllCountries { get; set; } } ``` The CountriesCollection object (line 9) looks like this: ``` public class CountriesCollection { [Display(Name = "Countries")] public int[] arrCountries { get; set; } } ``` Now, I'm creating a new, blank instance of CountriesCollection and then adding it to a blank instance of the DirectorySearchModel view model and then serialising it all into a javascript view model for Knockout.js: ``` { "FirstName":null, "LastName":null, "Countries":{"arrCountries":[]}, "SelectedCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}], "AllCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}] } ``` My checkboxes are rendered as: `<input checked="checked" data-bind="checked: Countries.arrCountries" id="Countries_arrCountries30" name="Countries.arrCountries" type="checkbox" value="1">`. Checking a couple means you end up with this Knockout.js view model: ``` { "FirstName":null, "LastName":null, "Countries":{"arrCountries":["1", "3"]}, "SelectedCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}], "AllCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}] } ``` Submitting my view normally (i.e. via a submit button and not with Knockout.js) to an MVC action that expects a `DirectorySearchModel`, I'm able to ask for `model.Countries.arrCountries` to get a list of the checked items, but when I use... ``` $.post("/MyController/MyAction", ko.toJS(viewModel), function(returnData) { $("#resultCount").html(returnData); }); ``` or... ``` $.post("/MyController/MyAction", viewModel, function(returnData) { $("#resultCount").html(returnData); }); ``` to another action that expects the same `DirectorySearchModel`, `model.Countries.arrCountries` is always `null`! I wondered if it's due to Knockout.js posting the `arrCountries` entries as `string[]`s when MVC is expecting `int[]`s, but changing my MVC code to expect `string[]`s doesn't seem to change much..! The `CountriesCollection` object within the `DirectorySearchModel` appears to exist, but it's the `arrCountries` within that's always `null`. Any ideas? Any help much appreciated! Edit The action that receives the Knockout.js viewModel: ``` public MvcHtmlString ResultCount(DirectorySearchModel model) { return new MvcHtmlString(getResultCount(model).ToString()); } ``` The `getResultCount` method: ``` public int getResultCount(DirectorySearchModel model) { IUserRepository userRepository = new UserRepository(); int count = userRepository.Search(model, null).Count(); return count; } ``` FIXED! Thanks to Konstantin for pointing out that a simple switch from $.post to $.ajax to send my Knockout.js view model back to my mvc action was all that was needed! Here's the $.ajax code I'm using: ``` $.ajax({ type: "POST", url: "/MyController/MyAction", data: ko.toJSON(viewModel), contentType: "application/json; charset=utf-8", dataType: "json", success: function (data) { $("#resultCount").html(data); } }); ```