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 create a new, empty instance of AssemblyCollection, and then add it to an empty instance of the DirectorySearchModel view model, and then serialize it all into the 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 appear as: <input checked="checked" data-bind="checked: Countries.arrCountries" id="Countries_arrCountries30" name="Countries.arrCountries" type="checkbox" value="1">
. Checking the pair means that you will fall into 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"}] }
Sending my view usually (i.e. via the submit button, and not with Knockout.js) to an MVC action waiting for DirectorySearchModel
, I can ask model.Countries.arrCountries
to get a list of 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
always null
! I was wondering if this is because Knockout.js sends arrCountries
entries as string[]
when MVC expects int[]
s, but changing my MVC code to expect string[]
seems to have changed little ..! The CountriesCollection
object within the DirectorySearchModel
exists, but it arrCountries
inside this is always null
.
Any ideas? Any help is much appreciated!
Edit
Action that gets the Knockout.js view:
public MvcHtmlString ResultCount(DirectorySearchModel model) { return new MvcHtmlString(getResultCount(model).ToString()); }
getResultCount
method:
public int getResultCount(DirectorySearchModel model) { IUserRepository userRepository = new UserRepository(); int count = userRepository.Search(model, null).Count(); return count; }
FIXED!
Thanks to Konstantin, pointing out that the easy transition from $ .post to $ .ajax to send my Knockout.js view model back to my mvc action was all that was needed! Here is 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); } });