Need to pass initial viewmodel data from ASP.NET MVC to knockout.js
Solution 1
The Json
method you are calling in your controller is meant to return a JsonResult
it does not create a JSON string. You would use this method to return json from an ajax call.
To return a JSON string to a view use something like this.
JavaScriptSerializer serializer = new JavaScriptSerializer();
ViewBag.InitialData = serializer.Serialize(people);
Then in your view code
<script>
var initialData = '@Html.Raw(ViewBag.InitialData)';
....
</script>
To answer your second question. In order to pass global list data such as this simply define a new class ContactsList
e.g
public class ContactsList
{
public string Name { get;set; }
public string Owner { get;set; }
public IList<People> People { get;set; }
}
Populate this and pass this to the JavascriptSerializer
instead. You will obviously need to adjust your js ContactsModel
accordingly.
EDIT
Here's a jsfiddle that demonstrates the changes needed.
http://jsfiddle.net/madcapnmckay/jRjwU/
Hope this helps.
Solution 2
You could also use your model instead of the ViewBag:
Controller:
public ActionResult Index()
{
var data= GetYourDataFromSomewhere();
return View(data);
}
View:
@model IEnumerable<ModelName>
....
<script type="text/javascript">
$(document).ready(function () {
var dataForKO = new KOViewModel(@Html.Raw(Json.Encode(Model)));
Solution 3
as far as the first part of the question is concerned you can try
<script>
var initialData = '@Html.Raw(ViewBag.InitialData)'; //get the raw json
var parsedJSON = $.parseJSON(initialData); //parse the json client side
ko.applyBindings(new ContactsModel(parsedJSON));
</script>
the second part i really haven't understood...
Yasir
Updated on August 01, 2022Comments
-
Yasir almost 2 years
I was looking at the Contacts editor sample on the knockout.js website:
http://knockoutjs.com/examples/contactsEditor.html
The sample works perfectly, but I needed to make two changes to it:
- Pass the initial data from ASP.NET MVC 3 controller action method. Here is the code from the server:
Classes
public class Phone { public string Type { get; set; } public string Number { get; set; } } public class Person { public string FirstName { get; set; } public string LastName { get; set; } public List<Phone> Phones { get; set; } }
Sample Controller side code
List<Phone> phoneList = new List<Phone>(); Person p1 = new Person() { FirstName = "Abc", LastName = "Xyz" }; Phone phone1 = new Phone() { Type = "Home", Number = "1111111111" }; Phone phone2 = new Phone() { Type = "Mobile", Number = "1111111112" }; phoneList.Add(phone1); phoneList.Add(phone2); p1.Phones = phoneList; List<Phone> phoneList2 = new List<Phone>(); Person p2 = new Person() { FirstName = "Pqr", LastName = "Stu" }; Phone phone3 = new Phone() { Type = "Home", Number = "1111111113" }; Phone phone4 = new Phone() { Type = "Mobile", Number = "1111111114" }; phoneList2.Add(phone3); phoneList2.Add(phone4); p2.Phones = phoneList2; people.Add(p1); people.Add(p2); ViewBag.InitialData = Json(people, JsonRequestBehavior.AllowGet);
- Apart from rows of contacts that are part of the ViewModel, I also need to pass some data (e.g. ContactListName and ContactListOwner) that doesn't belong to the rows of contacts but to the ViewModel itself. These properties will be shown outside the grid of contacts.
I would really appreciate if someone can help me with this.
-
Raj about 12 yearsThis is what I do and I call this class ContactsViewModel instead of ContactList. Views are bind to ViewModel classes instead of Model.
-
Yasir about 12 yearsThanks @madcapnmckay for your answer. I tried the code you gave but it adds tens and tens of blank rows instead of the two rows that I am passing in my viewbag. Am I missing something?
-
Yasir about 12 yearsAlso, I am not calling any ajax method for the initial data load. Would this make any difference? I am setting ViewBag.InitialData in the Index() action method of my controller. This method is being used to render the view for the first time.
-
Yasir about 12 yearsThanks @3nigma for the code for the first part. It works. I have edited the description of the second part in the question. Hope it is clearer now.
-
madcapnmckay about 12 yearsThe lack of ajax doesn't matter. I forgot to include the Raw statement previously. I've added a JsFiddle that demonstrates the changes you'll need to make to the sample.
-
Yasir about 12 yearsGot the second part working as well based upon @madcapnmckay's answer. Thanks for all your help.
-
Yasir about 12 yearsHello, @madcapnmckay. I tried to replicate this example into the actual business scenario that I have and somehow binding is not working. Would you be able to look into stackoverflow.com/questions/9673052/…? Thanks in advance.