简体   繁体   English

Grpc.Core.RpcException“无法反序列化响应消息..”或“InvalidOperationException:长度不匹配”

[英]Grpc.Core.RpcException "Failed to deserialize response message.." or "InvalidOperationException: Length mismatch"

I am running a gRPC service on .NET Core 3.1 and trying to make calls from a .NET Framework 4.7.2 client.我在 .NET Core 3.1 上运行 gRPC 服务,并尝试从 .NET Framework 4.7.2 客户端进行调用。 I'm using protobuf-net to reuse existing WCF data contracts.我正在使用 protobuf-net 重用现有的 WCF 数据合约。 I've noticed the following unexpected client-side behavior today when one of the fields of a response object is non-null.今天,当响应 object 的字段之一为非空时,我注意到以下意外的客户端行为。

Grpc.Core.RpcException: 'Status(StatusCode="Internal", Detail="Failed to deserialize response message.")

  • Packages : protobuf-net v2.4.4 , Grpc v2.30.0, protobuf-net.Grpc v1.0.90, protobuf-net.Grpc.Native v1.0.90, Google.Protobuf v3.12.2:protobuf-net v2.4.4 ,Grpc v2.30.0,protobuf-net.Grpc v1.0.90,protobuf-net.Grpc.Native v1.0.90,Google.Protobuf v3.12.2

Here is an example that illustrates the general structure of the data contracts - in this case, Response<PersonData> is the response and PersonDataList is the non-null field.这是一个说明数据协定一般结构的示例 - 在这种情况下, Response<PersonData>是响应, PersonDataList是非空字段。

   [DataContract]  
   public class Response<TValue>{
         [DataMember(Order = 1)]
         public TValue Value; 
    }

   [DataContract]  
   public class PersonData : Data {
         [DataMember(Order = 1)]
         public IList<PersonDataItem> PersonDataList; 
    }
    
    [DataContract]
    public PersonDataItem {
         [DataMember(Order = 1)] 
         public PersonDataType Type {get; private set;}
    
         [DataMember(Order = 2)] 
         public DateTime? Time {get; private set;}
    
         ....
         [DataContract]
         public enum PersonDataType : int {
    
               [EnumMember]
               Child = 1, 
               [EnumMember]
               Adult = 2
         }
    }
    
    [DataContract]
    [ProtoInclude(1, typeof(PersonData)]
    public class Data {
         [DataMember(Order = 1)]
         public string Name
    }

What stumps me is that I use a similar or same pattern in other data contracts, which throw no exceptions when deserializing the response.让我难过的是,我在其他数据合约中使用了类似或相同的模式,在反序列化响应时不会抛出异常。 I did some searching and found this issue from 2019 that points to different Google.Protobuf versions as a possible source of error (but that doesn't seem to be the case here).我做了一些搜索,发现这个问题从 2019 年开始指向不同的 Google.Protobuf 版本作为可能的错误来源(但这里似乎不是这种情况)。

Has anyone seen this exception before?有没有人见过这个异常? I'm not sure if this is an issue with my data contracts or perhaps with some package version mismatch.我不确定这是否与我的数据合同有关,或者可能与某些 package 版本不匹配有关。 Any ideas or suggestions are very appreciated!任何想法或建议都非常感谢!

I also attempted updating to protobuf-net v3.0.0 but got a new client-side exception for every client call: Grpc.Core.RpcException: 'Status(StatusCode="Unknown", Detail="Exception was thrown by handler. InvalidOperationException: Length mismatch; calculated '63', actual '58'"...) This seems to be a different issue, and my current guess is that it may be related to the breaking changes re: dynamic typing in protobuf-net v3 .我还尝试更新到 protobuf-net v3.0.0 ,但每次客户端调用都会出现新的客户端异常: Grpc.Core.RpcException: 'Status(StatusCode="Unknown", Detail="Exception was thrown by handler. InvalidOperationException: Length mismatch; calculated '63', actual '58'"...)这似乎是一个不同的问题,我目前的猜测是它可能与 re: dynamic typing in protobuf-net v3的重大变化有关。

I am using Visual Studio 2022 Preview and I am facing this problem.我正在使用 Visual Studio 2022 Preview,我正面临这个问题。

As mentioned here , there is a bug in Visual Studio 2022.如此所述,Visual Studio 2022 中存在一个错误。

I applied the following work around mentioned and it worked for me.我应用了以下提到的工作,它对我有用。 See the screen shots below.请参阅下面的屏幕截图。

Set 'Hot Reload CSS changes' to false as follows.将“热重载 CSS 更改”设置为 false,如下所示。

Visual Studio 2022 中的工具选项

热重载 CSS 更改

Frankly, this sounds like a bug in protobuf-net that you should log on GitHub, ideally with a repro that also shows the service contract (interface).坦率地说,这听起来像是 protobuf-net 中的一个错误,您应该登录 GitHub,理想情况下,使用还显示服务合同(接口)的 repro。

The types should look reasonable.类型应该看起来合理。 The length mismatch at the end is particularly alarming, but I do not believe that this has any relationship to the dynamic types discussion.最后的长度不匹配特别令人担忧,但我认为这与动态类型讨论没有任何关系。

Happy to help investigate here (I'm the author), but: this sounds more like a GitHub thing.很高兴在这里帮助调查(我是作者),但是:这听起来更像是 GitHub 的事情。

I suspect that the length difference is related to Data not being a proto-contract (so it is questionable as to whether the proto-include is being respected; this is reinforced by the var that there would be duplicate fields 1 if it were), but a proper repro would really help.怀疑长度差异与Data不是原型合同有关(因此,是否尊重 proto-include 是有问题的;var 加强了这一点,即如果是,则会有重复的字段 1),但是适当的复制确实会有所帮助。

The following seems to work - the only changes to your code is to make sure that Data is marked as a ProtoContract , use a different number for the "include" part, and to add a Create method to PersonDataItem for the test harness to use;以下似乎有效 - 对代码的唯一更改是确保Data被标记为ProtoContract ,为“包含”部分使用不同的数字,并向PersonDataItem添加一个Create方法以供测试工具使用; it is hard to know how much of the problem this accounts for without a repro.如果没有复制,很难知道这占了多大的问题。

using ProtoBuf;
using ProtoBuf.Meta;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;

[DataContract]
public class Response<TValue>
{
    [DataMember(Order = 1)]
    public TValue Value;
}

[DataContract]
public class PersonData : Data
{
    [DataMember(Order = 1)]
    public IList<PersonDataItem> PersonDataList;
}

[DataContract]
public class PersonDataItem
{
    public static PersonDataItem Create(PersonDataType type, DateTime? time)
        => new PersonDataItem { Type = type, Time = time };
    [DataMember(Order = 1)]
    public PersonDataType Type { get; private set; }

    [DataMember(Order = 2)]
    public DateTime? Time { get; private set; }


    [DataContract]
    public enum PersonDataType : int
    {

        [EnumMember]
        Child = 1,
        [EnumMember]
        Adult = 2
    }
}

[ProtoContract, DataContract]
[ProtoInclude(10, typeof(PersonData))]
public class Data
{
    [ProtoMember(1), DataMember(Order = 1)]
    public string Name;
}

static class P
{
    static void Main()
    {
        var resp = new Response<PersonData>
        {
            Value = new PersonData
            {
                Name = "abc",
                PersonDataList = new List<PersonDataItem>
                {
                    PersonDataItem.Create(PersonDataItem.PersonDataType.Adult, DateTime.Now),
                }
            }
        };
        var clone = RoundTrip(resp);
        Console.WriteLine(clone.Value.Name);
        var item = clone.Value.PersonDataList.Single();
        Console.WriteLine(item.Time);
        Console.WriteLine(item.Type);
    }
    static T RoundTrip<T>(T value)
    {
        var model = RuntimeTypeModel.Default;
        using var state = model.Measure<T>(value);
        using var ms = new MemoryStream();
        state.Serialize(ms); // we expect this to explode if there was a length mismatch
        ms.Position = 0;
        return model.Deserialize<T>(ms);
    }
}

There are two causes for this error此错误有两个原因

  1. If you are using IIS to host the gRPC server there are some features that are not yet supported in ISS hence using Kestrel instead should fix the bug.如果您使用 IIS 托管 gRPC 服务器,则 ISS 中尚不支持某些功能,因此使用 Kestrel 应该可以修复该错误。
  2. Explained by @vivekDev there is a bug in Visual Studio 2022 preview and turning off Hot Reload For Css should fix the bug @vivekDev 解释说,Visual Studio 2022 预览中存在一个错误,关闭 Css 的热重载应该可以修复该错误

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Grpc.Core.RpcException:'状态(状态代码=“不可用”,详细信息=“空更新”, - Grpc.Core.RpcException: 'Status(StatusCode=“Unavailable”, Detail=“Empty update”, Google Vision API无法正常运行Grpc.Core.RpcException - Google Vision API not working Grpc.Core.RpcException Grpc.Core.RpcException: 'Status (StatusCode = "Unavailable", Detail = "Error starting gRPC call - Grpc.Core.RpcException: 'Status (StatusCode = "Unavailable", Detail = "Error starting gRPC call 从 .NET MAUI 应用程序调用 gRPC 服务时出现 Grpc.Core.RpcException - Grpc.Core.RpcException when calling gRPC service from .NET MAUI app 为什么要通过Google Cloud Firestore 1.0.0-beta05 C#SetAsync获取Grpc.Core.RpcException StatusCode =不可用,Detail =“连接失败”? - Why getting Grpc.Core.RpcException StatusCode=Unavailable, Detail=“Connect Failed”, with Google Cloud Firestore 1.0.0-beta05 C# SetAsync? Grpc.Core.RpcException StatusCode Unavailable Channel 处于状态 TRANSIENT_FAILURE - Grpc.Core.RpcException StatusCode Unavailable Channel is in state TRANSIENT_FAILURE Grpc.Core.RpcException 方法未在 C# 客户端和 Java 服务器中实现 - Grpc.Core.RpcException method is unimplemented with C# client and Java Server 从ASP.NET在本地访问Google Cloud Datastore会引发Grpc.Core.RpcException:“缺少权限或权限不足。” - Accessing Google Cloud Datastore locally from ASP.NET throws Grpc.Core.RpcException: “Missing or insufficient permissions.” GRPC-web RPCException 错误的 gRPC 响应。 无效的内容类型值:text/html; 字符集=utf-8 - GRPC-web RPCException Bad gRPC response. Invalid content-type value: text/html; charset=utf-8 DESERIALIZE上的InvalidoperationException - InvalidoperationException on DESERIALIZE
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM