将复杂的knockout可观察数组传递给Web Api

时间:2014-04-27 14:50:22

标签: asp.net-mvc knockout.js asp.net-web-api asp.net-web-api2 knockout-3.0

我有一个使用knockout和Web Api 2的MVC 5项目。

我的分页实现了我的淘汰赛模型最初由第一页填充,底部分页。允许用户导航到结果集中的其他页面。

代码如下:

在选中复选框时将Photo Id推送到可观察数组的Html标记:

<span>Add</span><input type="checkbox" class="photo" name="selected-photos" id="selected-photos" data-bind="checked:$root.selectedPhotos, checkedValue: $data.PhotoId" />

淘汰视图模型

function FlickrPhotosViewModel() {

    var self = this;

    self.photos = ko.observableArray([]);
    self.noOfPages = ko.observable();

    self.selectedPhotos = ko.observableArray([]);

    self.pageNumber = ko.observable(1);
    self.selectPage = function(pageNumber) {

        jQuery.support.cors = true;
        $.ajax({
            url: '@Url.RouteUrl("DefaultApi", new {httproute = "", controller = "PhotosFromFlickr"})',
            type: 'GET',
            data: { pageNumber: ko.toJSON(pageNumber), selectedPhotos: ko.toJSON(self.selectedPhotos()) },
            dataType: 'json',
            success: function(data) {
                self.photos(ko.mapping.fromJS(data.Photos));
                self.noOfPages(data.NoOfPages);
                self.selectedPhotos(data.SelectedPhotos);
            },
            error: function(x, y, z) {
                alert(x + '\n' + y + '\n' + z);
            }
        });
    };

    jQuery.support.cors = true;

    $.ajax({
        url: '@Url.RouteUrl("DefaultApi", new {httproute = "", controller = "PhotosFromFlickr"})',
        type: 'GET',
        data: { pageNumber: ko.toJSON(self.pageNumber()), selectedPhotos: ko.toJSON(self.selectedPhotos()) },
        dataType: 'json',
        success: function (data) {
            self.photos(ko.mapping.fromJS(data.Photos));
            self.noOfPages(data.NoOfPages);
        },
        error: function (x, y, z) {
            alert(x + '\n' + y + '\n' + z);
        }
    });
};

$(document).ready(function () {
    ko.applyBindings(new FlickrPhotosViewModel());
});

网络Api获取方法 这当前有两个参数,第一个是我想要提供的页码,第二个是所选的照片ID,目前作为字符串传递。

public PhotoCollectionModel Get(int pageNumber, string selectedPhotos )
    {}

我遇到的问题是我希望第二个参数是强类型的。或者至少列出selectedPhotos。目前我不得不在Web Api Get方法中反序列化json字符串(selectedPhotos)...

这可能还是我错过了这一点?

更新

这是它创建的请求网址 -

http://localhost/Mvc/api/PhotosFromFlickr?pageNumber=3&selectedPhotos=%5B%228060459369%22%2C%227895411674%22%2C%227067757145%22%5D

标题是:

Request Headers :

Accept:application/json, text/javascript, */*; q=0.01
Referer:http://localhost/Mvc/Profile?username=MarkHBrown
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36
X-Requested-With:XMLHttpRequest

3 个答案:

答案 0 :(得分:1)

如上所述,您必须使用[FromUri]属性修饰方法参数。此外,您可以在查询字符串中传递数组,如下所示:?selectedPhotos=[1,2,3]

正确的方法是?selectedPhotos=1&selectedPhotos=2&selectedPhotos=3

答案 1 :(得分:0)

Web API应该可以正常使用您的代码,但您也应该更改操作参数..

public PhotoCollectionModel Get([FromUri]int pageNumber, [FromUri]IEnumerable<Photo> selectedPhotos )
    {}

照片是一种与javascript中的类型结构相匹配的类型...或者如果您只是发送照片的ID,那么类似下面的内容应该没问题......

public PhotoCollectionModel Get([FromUri]int pageNumber, [FromUri]IEnumerable<int> selectedPhotos)
    {}

答案 2 :(得分:0)

我已按照原来的要求设法让它正常工作。

我希望能够传递我提交时已选择的复杂照片对象。为了实现这一点,我不得不使用GET(因为它使用查询字符串)并使用POST代替。

我已将pageNumber保留在url中,并通过我的jQuery ajax调用的data参数传递了请求正文中的observableArray。

以下是代码:

Web Api发布方法

public PhotoCollectionModel Post([FromUri]int pageNumber, [FromBody]Photo[] selectedPhotos)
    {}

jQuery ajax Post - 通过附加到html元素上的click事件的knockout函数调用

self.selectedPhotos是这种情况下的类型对象(Photo)的数组。

jQuery.support.cors = true;
                $.ajax({
                    url: '@Url.RouteUrl("DefaultApi", new {httproute = "", controller = "PhotosFromFlickr"})/?pageNumber=' + pageNumber,
                    type: 'POST',
                    data: ko.toJSON(self.selectedPhotos),
                    dataType: 'json',
                    contentType: 'application/json; charset=utf-8',
                    success: function (data) {
                        self.photos(ko.mapping.fromJS(data.Photos));
                        self.noOfPages(data.NoOfPages);
                    },
                    error: function (x, y, z) {
                        alert(x + '\n' + y + '\n' + z);
                    }
                });

我的复选框标记

<span>Add</span><input type="checkbox" class="photo" name="selected-photos" id="selected-photos" data-bind="data-bind="checkedValue: $data, checked: $root.selectedPhotos" />" />

我现在面临的问题是,当回到以前的页面时,它不会保持检查状态......但如果我将照片ID存储在可观察数组中,则可以正常工作。

话虽如此 - 如果您没有分页,这是一个很好的解决方案......