Как использовать IEnumerable‹ExpandoObject› в Knockout.js?

Описание проблемы

Я хотел спросить о том, как использовать список объектов Exbando в Knockout.js, я использую Massive Роба Конри, и все возвращаемые результаты являются динамическими, меня это устраивает, это соответствует моим потребностям, но когда дело доходит до отправки результатов в нокаут, я просто не знаю не знаю, что с этим делать.

Цель

Доступ к свойствам объекта, таким как obj.Name, obj.Brand и т. д.

Пример кода

Просмотр:

<div data-bind="foreach: Products">
    <p>Product name: <strong data-bind="text: Name"></strong></p>
</div>

Контроллер:

public JsonResult GetProducts() 
{
     Products products = new Products();
     var Model = products.GetAllProducts();
     return Json(Model, JsonRequestBehavior.AllowGet);
}

Результат вызова GetProducts:

[[{"Ключ":"Идентификатор","Значение":1},{"Ключ":"Имя","Значение":"Крутые сапоги"},{"Ключ":"Бренд","Значение": "Nike"},{"Key":"Description","Value":"Супер крутые ботинки, которые заставят вас летать (не совсем!").} и т. д...]]

Файл сценария:

function ProductListViewModel() {
    // Data
    var self = this;
    self.Products = ko.observableArray([]);

    $.getJSON("/Home/GetProducts", function (data) {
        self.Products(data);
    });
}

Ошибка JavaScript при запуске приложения:

Uncaught ReferenceError: невозможно проанализировать привязки. Значение привязки: текст: Имя Сообщение: Имя не определено

Снимок экрана 1:

введите здесь описание изображения

Снимок экрана 2:

введите здесь описание изображения


person Ibrahim Ahmed    schedule 29.09.2013    source источник
comment
так что здесь не работает?   -  person Tigran    schedule 29.09.2013
comment
Я получаю это сообщение об ошибке: Uncaught ReferenceError: невозможно проанализировать привязки. Значение привязки: текст: Имя Сообщение: Имя не определено   -  person Ibrahim Ahmed    schedule 29.09.2013


Ответы (3)


Вообще говоря, ExpandoObject во всех отношениях является словарем. При сериализации здесь как JSON он рассматривается как словарь и становится набором пар ключ/значение (не все сериализаторы ведут себя так, но тот, который вы используете). Это не объект, к членам которого вы можете получить доступ по имени, вам придется преобразовать его в представление, где вы можете (или сначала сериализовать его как единое целое).

Выполнение преобразования — не самое худшее в мире:

function Product(item) {
    var self = this;
    // assuming item is an array of key/value pairs
    ko.utils.arrayForEach(item, function(pair) {
        // doesn't necessarily have to be mapped as an observable
        self[pair.Key] = ko.observable(pair.Value);
    });
}

При этом вы можете сопоставить результаты с вашим набором продуктов:

$.getJSON("/Home/GetProducts", function (data) {
    self.Products(ko.utils.arrayMap(data, function(item) {
        return new Product(item);
    }));
});
person Jeff Mercado    schedule 29.09.2013
comment
Я не знаю, как сериализация работает в ASP.net и можно ли ее вообще настроить. Но я обычно использую Json.NET для всех моих потребностей JSON, и он сериализует словари как объекты, а не как наивная коллекция пар ключ/значение. Возможно, вы могли бы использовать Json.NET здесь... Я просто не знаю, как это настроить. - person Jeff Mercado; 29.09.2013

Похоже, проблема в том, что вы пытаетесь установить значение вашего ko.observableArray в массив json. Не уверен, что это сработает. Обычно я делаю так:

function ProductListViewModel() {
   // Data
   var self = this;
   self.Products = ko.observableArray([]);

   $.getJSON("/Home/GetProducts", function (data) {
       ko.utils.arrayForEach(data, function(item) {
           self.Products.push({
               Name : item.Name
           });
       });
   });

}

Используйте функцию нокаута arrayForEach, чтобы перебирать ваш массив json и помещать каждый объект в ваш observableArray.

person officert    schedule 29.09.2013
comment
Я сделал это, и я также получаю Uncaught ReferenceError: невозможно проанализировать привязки. Значение привязки: текст: Имя Сообщение: Имя не определено - person Ibrahim Ahmed; 29.09.2013
comment
Не могли бы вы опубликовать, что такое класс продуктов С#. Глядя на JSON, который вы получаете с сервера, что-то выглядит не так. У вас есть массив внутри массива, и каждое из ваших свойств классов Product является объектами, что кажется неправильным. Я думаю, что ваш продукт будет выглядеть примерно так: { 'Id' : '1', 'Name' : 'BadAss Boots'}. Каждый продукт в вашей коллекции — это один объект Json с некоторыми свойствами. - person officert; 29.09.2013
comment
Спасибо за вашу помощь я очень благодарен :); - person Ibrahim Ahmed; 29.09.2013

Как и в вашем JSON, я вижу последовательность Key и Value, поэтому вам нужно указать имя файла, которое нокаут должен запросить, чтобы получить относительное значение и вывести его на экран.

Так что измените <strong data-bind="text: Name"> на <strong data-bind="text: Key">, и это должно работать для вас.

person Tigran    schedule 29.09.2013