【问题标题】:Need to pass initial viewmodel data from ASP.NET MVC to knockout.js需要将初始视图模型数据从 ASP.NET MVC 传递给 knockout.js
【发布时间】:2026-01-05 04:05:02
【问题描述】:

我正在查看 knockout.js 网站上的联系人编辑器示例:

http://knockoutjs.com/examples/contactsEditor.html

该示例运行良好,但我需要对其进行两处更改:

  • 从 ASP.NET MVC 3 控制器操作方法传递初始数据。这是来自服务器的代码:

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; }
}

示例控制器端代码

       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);
  • 除了作为 ViewModel 一部分的联系人行之外,我还需要传递一些不属于联系人行但属于 ViewModel 本身的数据(例如 ContactListName 和 ContactListOwner)。这些属性将显示在联系人网格之外。

如果有人能帮我解决这个问题,我将不胜感激。

【问题讨论】:

  • ViewBag.InitialData 包含什么你能发布控制器代码吗?你打算在ko.applyBindings(new ContactsModel(initialData)); 中使用ViewBag.InitialData 吗?
  • 感谢@3nigma 的回复。我在我的问题中添加了控制器端代码。是的,如果可能的话,我打算在 ko.applyBindings(new ContactsModel(initialData)) 中使用 ViewBag.InitialData。

标签: json asp.net-mvc-3 knockout.js viewmodel


【解决方案1】:

您在控制器中调用的Json 方法旨在返回JsonResult,它不会创建JSON 字符串。您将使用此方法从 ajax 调用返回 json。

要将 JSON 字符串返回到视图,请使用类似这样的方法。

JavaScriptSerializer serializer = new JavaScriptSerializer();
ViewBag.InitialData = serializer.Serialize(people); 

然后在你的视图代码中

<script>
    var initialData = '@Html.Raw(ViewBag.InitialData)';
    ....
</script>

回答你的第二个问题。为了传递这样的全局列表数据,只需定义一个新类ContactsList 例如

public class ContactsList 
{
    public string Name { get;set; }
    public string Owner { get;set; }
    public IList<People> People { get;set; }
}

填充此并将其传递给JavascriptSerializer。您显然需要相应地调整您的 js ContactsModel

编辑

这是一个演示所需更改的 jsfiddle。

http://jsfiddle.net/madcapnmckay/jRjwU/

希望这会有所帮助。

【讨论】:

  • 这就是我所做的,我将这个类称为 ContactsViewModel 而不是 ContactList。视图绑定到 ViewModel 类而不是模型。
  • 感谢@madcapnmckay 的回答。我尝试了您提供的代码,但它添加了数十行和数十行空白行,而不是我在视图包中传递的两行。我错过了什么吗?
  • 另外,我没有为初始数据加载调用任何 ajax 方法。这会有什么不同吗?我在控制器的 Index() 操作方法中设置 ViewBag.InitialData。首次使用此方法渲染视图。
  • 没有ajax也没关系。我之前忘记包含 Raw 语句。我添加了一个 JsFiddle 来演示您需要对示例进行的更改。
  • 你好,@madcapnmckay。我试图将此示例复制到我拥有的实际业务场景中,但不知何故绑定不起作用。你能看看*.com/questions/9673052/…吗?提前致谢。
【解决方案2】:

你也可以使用你的模型而不是 ViewBag:

控制器:

        public ActionResult Index()
        {
            var data= GetYourDataFromSomewhere();

            return View(data);
         }

查看:

@model IEnumerable<ModelName>

....

<script type="text/javascript">
    $(document).ready(function () {

        var dataForKO = new KOViewModel(@Html.Raw(Json.Encode(Model)));

【讨论】:

    【解决方案3】:

    就问题的第一部分而言,您可以尝试

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

    第二部分真的没看懂……

    【讨论】:

    • 感谢@3nigma 提供第一部分的代码。有用。我已经编辑了问题第二部分的描述。希望现在更清楚了。
    • 根据@madcapnmckay 的回答,第二部分也能正常工作。感谢您的所有帮助。