【问题标题】:Unable to deserialize array via GET无法通过 GET 反序列化数组
【发布时间】:2014-09-10 00:49:48
【问题描述】:

我正在使用 Kendo UI 的 DataSource 将排序信息发送到我的 ServiceStack 服务。我知道这个has been addressed 如果您使用的是POST,但我想坚持RESTful 设计,所以请求动词需要是GET。我正在使用这个 sn-p 进行测试:

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** 请求。

【问题讨论】:

    标签: c# jquery json kendo-ui servicestack


    【解决方案1】:

    您不能将复杂的数据结构(例如锯齿状排序数组的数据结构)与使用标准技术的 GET 请求一起使用,因为 JSON GET 请求仅支持简单变量,因为这些变量可以转换为查询字符串中的请求参数.因此,对于简单参数 ?Page=2&amp;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&lt;SortTerm&gt;

    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; }
    }
    

    我希望这会有所帮助。

    【讨论】:

    • 正如你所说,我想出来的总体原因是 GET 无法合理地传递复杂的数据结构。虽然我说客户端或服务器端修复都可以,但我更喜欢服务器端来保持客户端代码干净,并且与后端无关。我已经在下面的答案中发布了我的代码。
    • @jklemmack 是的,尽可能保持客户端清洁是合理的,因此您的解决方案看起来也很合适(+1)。
    【解决方案2】:

    Scott 上面的答案是正确的,但这是我更以服务器为中心的解决方案。基本上,我从查询字符串中手动重建 SortTerm 对象。这可以扩展到其他特定于 Kendo 的参数,例如过滤器和组。

    客户端代码:

    <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++;
            }
        }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      相关资源
      最近更新 更多