SignalR和Knockout视图模型绑定

时间:2014-02-09 16:52:32

标签: asp.net-mvc knockout.js signalr

我正在尝试使用signalr和knockout.js显示数据库中的产品列表。但没有任何结果。谁能告诉我我做错了什么或我哪里弄错了?我将非常感谢帮助我。 这是观点:

<div class="products">
    <div class="row" data-bind="template: { name: 'productTemplate', foreach: products }">
    </div>
    <span class="messageClass" style="color: red;"></span>
</div>

<script type="text/html" id="productTemplate">
    <div class="col-sm-6 col-md-4">
        <div class="thumbnail">
            <div class="caption">
                <h3 data-bind="text: name"></h3>
            </div>
        </div>
    </div>
</script>

这是剧本:

<script>
        $(function () {
            function productViewModel(id, name) {
                this.productId = id;
                this.name = ko.observable(name);
                var self = this;
            }

            function productListViewModel() {
                this.hub = $.connection.voteHub;
                this.products = ko.observableArray([]);

                var products = this.products;

                this.init = function () {
                    this.hub.server.getAllProducts();
                }

                this.hub.client.getAllProducts = function (allProducts) {
                    var mappedProducts = $.map(allProducts, function (item) {
                        return new productViewModel(item.productId, item.name)
                    });

                    products(mappedProducts);
                }
            }

            var vm = new productListViewModel();
            ko.applyBindings(vm);

            $.connection.hub.start(function () {
                vm.init();
            });
        });
    </script>

以下是获取所有产品的中心方法:

public void GetAllProducts()
{
    VoteViewModel viewModel = new VoteViewModel();
    viewModel.Products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();

    if (viewModel.Products != null)
    {
        // TODO: pomyslec nad wysylaniem listy a nie tablicy!
        Clients.All.getAllProducts(viewModel.Products.ToArray());
    }
}

如果我像这样使用我的集线器代码,它将运行良好(取自演示应用程序):

VoteViewModel vm = new VoteViewModel();
vm.Products = new List<Product>() { new Product() { Name = "Sample", Id = 1 } };
Clients.All.getAllProducts(vm.Products.ToArray());

我看起来像这样的代码不起作用。 (我不知道为什么,也许是因为我的db产品对象有更多变量?):

VoteViewModel viewModel = new VoteViewModel();
viewModel.Products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
Clients.All.getAllProducts(viewModel.Products.ToArray());

以下是我的Product类中的代码:(dbcontext类)

[Key]
public int Id { get; set; }

[Required]
public string Name { get; set; }

public string Description { get; set; }

[Required]
public string ImagePath { get; set; } 

public virtual ICollection<Vote> Votes { get; set; }

我制作了新的ProductViewModel类,如下所示:

public class ProductViewModel 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string ImagePath { get; set; }
    public int VotesAmount { get; set; }
}

然后将db中的所有数据绑定到该模型,然后返回List和IT WORKS NOW!,但我真的不明白为什么我不能只从数据库中获取产品列表并将其发送到信号器客户端(就像我之前尝试过的那样)。

    List<ProductViewModel> prods = new List<ProductViewModel>();
    List<Product> products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
    foreach (var item in products)
    {
        ProductViewModel prod = new ProductViewModel()
        {
            Id = item.Id,
            Name = item.Name,
            Description = item.Description,
            ImagePath = item.ImagePath,
            VotesAmount = item.Votes.Count()
        };
        prods.Add(prod);
    }

    Clients.All.getAllProducts(prods.ToArray());

1 个答案:

答案 0 :(得分:3)

您的代码绝对正常。请检查您是否参考了以下文件。

<script src="~/scripts/jquery.signalr-2.0.2.js" type="text/javascript"></script>
<script src="~/signalr/hubs"></script>

Signalr.hubs是提供javascripts代理文件的主要参考。如果您遇到任何错误,请告诉我。

接下来是模型对象创建中引用的属性名称。

           this.hub.client.getAllProducts = function (allProducts) {
                var mappedProducts = $.map(allProducts, function (item) {
                    return new productViewModel(item.productId, item.name)
                });

                products(mappedProducts);
            }

我已将属性名称更新为pascal case并为我工作。

return new productViewModel(item.ProductId, item.Name)