Need to pass initial viewmodel data from ASP.NET MVC to knockout.js

10,701

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...

Share:
10,701
Yasir
Author by

Yasir

Updated on August 01, 2022

Comments

  • Yasir
    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
    Raj about 12 years
    This is what I do and I call this class ContactsViewModel instead of ContactList. Views are bind to ViewModel classes instead of Model.
  • Yasir
    Yasir about 12 years
    Thanks @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
    Yasir about 12 years
    Also, 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
    Yasir about 12 years
    Thanks @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
    madcapnmckay about 12 years
    The 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
    Yasir about 12 years
    Got the second part working as well based upon @madcapnmckay's answer. Thanks for all your help.
  • Yasir
    Yasir about 12 years
    Hello, @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.