I am using MVC4 and trying knockoutjs library with it. The form submits the data to the controller if I use the traditional Submit click without using Knockoutjs library. I am using knockoutjs mapping plugin to convert the viewmodel from the server to create a client-side viewmodel and then trying to extend it client-side.
- To convert from server-side to client-side vm, I'm using
ko.mapping.fromJS(model); - To post the data back to the server, I'm converting it back by
ko.toJSON(model)while sending via ajax using jQuery.
The data that I receive on server is null. Also, when I log ko.toJSON(model) in console, I get the following:
{
"FirstName": "foo",
"LastName": "foo1",
"Address": "United Kingdom",
"Age": 22,
"__ko_mapping__": {
"ignore": [],
"include": ["_destroy"],
"copy": [],
"observe": [],
"mappedProperties": {
"FirstName": true,
"LastName": true,
"Address": true,
"Age": true
},
"copiedProperties": {}
}
}
It seems I am not doing right while converting the js object back to json format to send the data to the server. Below is all my code:
Controller Code:
public class PersonController : Controller
{
PersonViewModel viewModel = new PersonViewModel();
//
// GET: /Person/
[HttpGet]
public ActionResult Index()
{
return View(viewModel);
}
[HttpPost]
public ActionResult Index(PersonViewModel viewModel)
{
if (ModelState.IsValid)
{
}
return View(viewModel);
}
//
// GET: /Person/LoadData/
public ActionResult LoadData()
{
viewModel = new PersonViewModel() { FirstName = "foo", LastName = "foo1", Age = 22, Address = "United Kingdom" };
return Json(viewModel, JsonRequestBehavior.AllowGet);
}
}
ViewModel at Server:
public class PersonViewModel
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Address { get; set; }
[Required]
public int Age { get; set; }
}
ViewModel at client-side - JavaScript :
var Person = function () {
var self = this;
self.SetupKOBindings = function () {
var source = null;
this.GetViewModelFromServer = function () {
$.ajax(
{
url: "/Person/LoadData",
type: "GET",
async: false
}).
success(function (data) {
source = data;
});
}();
return ko.mapping.fromJS(source);
};
self.ViewModel = function () {
this.model = self.SetupKOBindings();
this.model.Save = function () {
console.log(ko.toJSON(model));
$.ajax(
{
url: "/Person/Index",
type: "POST",
data: ko.toJSON(model),
async: true
}).
success(function (data) {
});
}
return this.model;
};
self.ApplyKOBindings = function (vm) {
ko.applyBindings(vm);
};
return this;
};
$(function () {
var PersonPage = Person();
var viewModel = PersonPage.ViewModel();
PersonPage.ApplyKOBindings(viewModel);
});
HTML in .cshtml at server:
<form action="" method="post">
<div>
First Name:
@Html.TextBoxFor(model => model.FirstName, new { data_bind = "value: FirstName,valueUpdate:['afterkeydown','propertychange','input']" })<br />
</div>
<div>
Last Name:
@Html.TextBoxFor(model => model.LastName, new { data_bind = "value: LastName,valueUpdate:['afterkeydown','propertychange','input']" })<br />
</div>
<div>
Address:
@Html.TextBoxFor(model => model.Address, new { data_bind = "value: Address" })<br />
</div>
<div>
Age:
@Html.TextBoxFor(model => model.Age, new { data_bind = "value: Age" })<br />
</div>
<input type="submit" value="Save" data-bind="click: Save"/>
</form>