An ExpandoObject
generally speaking is for all intents and purposes, a dictionary. When serialized as JSON here, it is treated as a dictionary and becomes a collection of key/value pairs (not all serializers behave this way, but the one you're using does). It is not an object you can access members by name, you'll have to convert it into a representation where you can (or serialize it as one in the first place).
Doing the conversion is not the worst thing in the world:
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);
});
}
With this, you can then map the results to your array of products:
$.getJSON("/Home/GetProducts", function (data) {
self.Products(ko.utils.arrayMap(data, function(item) {
return new Product(item);
}));
});