如何在Simple OData Client中启用gzip压缩?

6
我将尝试使用Simple OData Client库执行查询,从CRM Dynamics检索信息,代码如下(C#):

var settings = new ODataClientSettings(resource + "/api/data/v8.0/");
settings.BeforeRequest = (request) =>
    {
        request.Headers.Clear();
        request.Headers.Add("Authorization", accesstoken.AccessTokenType + " " + accesstoken.AccessToken);
    };

settings.PayloadFormat = ODataPayloadFormat.Json;
var client = new ODataClient(settings);
var annotations = new ODataFeedAnnotations();

var transactions = await client.For("mss_transaccions").FindEntriesAsync(annotations);
while (annotations.NextPageLink != null)
{
    transactions = transactions.Union(await client.For("mss_transaccions").FindEntriesAsync(annotations.NextPageLink, annotations));
}

虽然这种方法可以运行,但是由于我在 mss_transaccions 表上的查询有7200个实体,所以非常缓慢。我正在 Fiddler 中查看输出,并且可以看到它试图下载大约20MB的信息。
我尝试在 Google Chrome 上运行相同的查询,并且可以看到默认情况下获得的响应以 gzip 格式压缩,从20MB减少到仅有的500KB左右。因此,我推断 Simple OData Client 没有进行任何类型的压缩,这就是为什么它如此缓慢的原因。
此外,OData Simple Client 的请求要求元数据信息,这会增加另外4MB的数据量,而 Chrome 或简单的 HttpClient 请求不需要进行该调用。
是否有任何方法可以改善并启用压缩?
谢谢。

我对OData客户端的使用经验很少,但您是否可以检查/设置/修改传出请求中的“Accept-Encoding: gzip、deflate”头?这至少可以使服务器开始压缩。然后希望客户端使用某些流来解压它。 - Marvin Smit
@MarvinSmit 这就是为什么这不是一个 OData 问题,而是一个 Simple.Odata 问题 - 这是一个特定的客户端库。鉴于出站请求由库管理,修改它并不像听起来那么简单(如果库不支持它)。从技术上讲,是的,一个人“只需”子类化 HttpClient 并使其提交压缩头信息... 但如何在 Simple.Odata 中实现呢?我也面临同样的问题 ;) - TomTom
根据您上面的代码,我会期望一个“beforesend” -> “Headers.Add”的接受类型,并尝试它运行? - Marvin Smit
3个回答

2
在你的BeforeRequest操作中,添加如下Accept-Encoding标头:
settings.BeforeRequest = (request) =>
{
    // ... other headers as above
    request.Headers.Add("Accept-Encoding", "gzip");
};

如果我在请求头中添加"Accept-Encoding","gzip",我会收到'',十六进制值0x1F,是无效字符。行1,位置1。错误 - undefined

2
我终于能够启用压缩并加速整个过程。完整的讨论可以在这里找到:https://github.com/object/Simple.OData.Client/issues/238 简单来说,您只需要使用以下代码修改ODataSettings实例中的消息处理程序:
settings.OnApplyClientHandler = handler =>
            {
                handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
            };

现在,http请求以gzip、deflate的方式发送,并且响应时正确地进行了解压缩。

1
如果您检查Chrome正在发送哪些标头,并尝试在C#中复制它们,那么?
此外,如果我需要从C#访问CRM,我会使用Microsoft.Xrm.Sdk而不是OData。您有大量的代理类型和请求可以让您编写更清晰的代码。 OData还具有其他限制,而QueryExpressions / CRM LINQ / FetchXml也没有这些限制。
对于JS代码(即来自CRM表单的请求),OData更有意义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接