无法通过GET反序列化数组

时间:2014-07-18 19:34:30

标签: c# jquery json kendo-ui servicestack

我正在使用Kendo UI的DataSource向我的ServiceStack服务发送排序信息。如果您使用POST,我知道这个has been addressed,但我想遵守RESTful设计,因此请求动词必须是GET。我正在使用此代码段进行测试:

var dataSource = new kendo.data.DataSource({
        serverSorting: true,
        sort: [{ field: "ProductName", dir: "desc" },
               { field: "Category", dir: "asc"}],

        serverPaging: true,
        page: 2,
        pageSize: 5,

        transport: {

            read: {
                url: "/products",
                dataType: "json",
                contentType: "application/json",
                dataType: "jsonp"
            },

            parameterMap: function (data, type) {
                //return kendo.stringify(data);
                //return JSON.stringify(data);
                //return $.param(data, true);
                //data.sort = kendo.stringify(data.sort);
                return data;
            }
        }
    });

    dataSource.fetch(function () {
        console.log(dataSource.view());
    });

排序参数变为锯齿状数组,如:

sort[0][field]: ProductName
sort[0][dir]: desc
sort[1][field]: Category
sort[1][dir]: asc

我的请求DTO是:

    public class SortTerm
{
    public string field { get; set; }
    public string dir { get; set; }
}

public class KendoQuery
{

    public List<SortTerm> Sort { get; set; }

    public int Skip { get; set; }
    public int Take { get; set; }
    public int Page { get; set; }
    public int PageSize { get; set; }
}

所有简单参数都被反序列化,但是我怎样才能转换Sort属性(客户端或服务器端)以使其正确填充?

请注意,我在parameterMap函数中尝试了各种序列化技术,但我完全被困了。

修改

所以这一切归结为:当jQuery仔细地将我的请求重新排列成锯齿状数组时,如何通过$ .get()将对象数组传递给ServiceStack服务?这是一个请求过滤器的臭味,但我必须想象它之前已经解决了**GET**个请求。

2 个答案:

答案 0 :(得分:5)

您不能使用标准技术使用复杂数据结构(例如锯齿状排序数组)和GET请求,因为JSON GET请求仅支持简单变量,因为这些变量可以转换为请求参数在查询字符串中。因此,对于简单参数?Page=2&PageSize=5 ...,请求将正确形成,但对于sort[0][field],不能将其指定为查询字符串请求参数。

但是,如果您使用datasource.transport.parameterMap对搜索条件对象进行字符串化,则可以解决此问题,以便可以将其作为参数传递,然后在服务器上进行转换。

parameterMap: function (data, type) {
    // Convert the search criteria to a JSON string and store it on value sortJson
    data.sortJson = JSON.stringify(data.sort);

    // Remove the sort value, as this will be provided by sortJson
    delete data.sort;

    // Return the data
    return data
}

在服务器上,您需要处理将JSON字符串转换为List<SortTerm>

public class KendoQuery
{

    List<SortTerm> sort;
    public List<SortTerm> Sort {
         get {
             // Handles deserialising the SortJson value 
             if(sort == null)
                 sort = ServiceStack.JsonSerializer.DeserializeFromString<List<SortTerm>>(SortJson);
             return sort;
         }
    }

    public string SortJson { get; set; } 
    public int Skip { get; set; }
    public int Take { get; set; }
    public int Page { get; set; }
    public int PageSize { get; set; }
}

我希望这会有所帮助。

答案 1 :(得分:3)

斯科特上面的答案是正确的,但这是我更加以服务器为中心的解决方案。基本上,我从查询字符串手动重建SortTerm对象。这可以扩展到其他Kendo特定的参数,如Filters&amp;基团。

<强>客户端代码:

<html>
<head>
    <meta charset="utf-8">
    <title>Kendo UI Snippet</title>

    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://cdn.kendostatic.com/2014.1.528/js/kendo.all.min.js"></script>
</head>
<body>
    <script>
        var dataSource = new kendo.data.DataSource({
            serverSorting: true,
            sort: [{ field: "ProductName", dir: "desc" },
                   { field: "Category", dir: "asc" }],

            serverPaging: true,
            page: 2,
            pageSize: 5,

            transport: {
                read: {
                    url: "/products",
                    dataType: "json"
                }
            }
        });

        dataSource.fetch(function () {
            console.log(dataSource.view());
        });
    </script>
</body>
</html>

服务器代码(在AppHost实施中)

this.GlobalRequestFilters.Add((req, resp, dto) =>
{
    if (dto is KendoQueryBase)
    {
        KendoQueryBase qb = dto as KendoQueryBase;
        if (qb.Sort == null) qb.Sort = new List<SortTerm>();
        Dictionary<string, string> qs = req.QueryString.ToDictionary();
        var i = 0;
        while (qs.ContainsKey("sort[{0}][field]".Fmt(i)))
        {
            qb.Sort.Add(new SortTerm()
            {
                field = qs["sort[{0}][field]".Fmt(i)],
                dir = qs["sort[{0}][dir]".Fmt(i)]
            });
            i++;
        }
    }
});