首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Grpc.Core.RpcException“未能反序列化响应消息.”或"InvalidOperationException:长度不匹配“

Grpc.Core.RpcException“未能反序列化响应消息.”或"InvalidOperationException:长度不匹配“
EN

Stack Overflow用户
提问于 2020-08-04 04:25:21
回答 3查看 3.7K关注 0票数 3

我正在.NET Core3.1上运行一个.NET服务,并试图从.NET Framework4.7.2客户端进行调用。我正在使用protobuf来重用现有的WCF数据契约。今天,当响应对象的一个字段为非空时,我注意到了以下意外的客户端行为。

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

  • 软件包: protobuf-net v2.4.4,Grpc v2.30.0,protobuf-net.Grpc v1.0.90,protobuf net.Grpc.Nativev1.0.90,Google.Protobuf v3.12.2

这里有一个示例说明了数据契约的一般结构--在本例中,Response<PersonData>是响应,PersonDataList是非空字段。

代码语言:javascript
复制
   [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
    }

让我沮丧的是,我在其他数据契约中使用了类似或相同的模式,在反序列化响应时不会抛出异常。我进行了一些搜索,发现这一期从2019年开始将不同的Google.Protobuf版本作为可能的错误来源(但这里似乎并非如此)。

以前有人见过这个异常吗?我不确定这是我的数据契约的问题,还是包版本错配的问题。任何想法或建议都非常感谢!

我还尝试更新到protobuf v3.0.0,但是对于每个客户端调用都得到了一个新的客户端异常:,这似乎是一个不同的问题,我目前的猜测是,这可能与protobuf网v3中的破坏更改re:动态类型有关。

EN

回答 3

Stack Overflow用户

发布于 2021-09-16 07:39:03

我正在使用VisualStudio2022预览,我正面临这个问题。

正如前面提到的这里,VisualStudio2022中有一个bug。

我应用了下面提到的工作,它为我工作。请看下面的屏幕截图。

将“热重新发布CSS更改”设置为false,如下所示。

票数 5
EN

Stack Overflow用户

发布于 2020-08-04 06:48:46

坦率地说,这听起来像是protobuf-net中的一个bug,您应该登录到GitHub上,最好是使用同时显示服务契约(接口)的repro。

类型应该看上去很合理。最后的长度错配特别令人震惊,但我不认为这与动态类型讨论有任何关系。

很高兴在这里帮助调查(我是作者),但是:这听起来更像是一个GitHub的东西。

我怀疑,长度差异与Data不是原始合同有关(因此,对于原始包含是否得到尊重是有疑问的;这是由var强化的,如果有重复字段1的话),但是适当的复制确实会有所帮助。

下面的代码似乎有效--对代码的唯一更改是确保Data被标记为ProtoContract,对“包含”部分使用不同的数字,并向PersonDataItem添加一个Create方法以供测试工具使用;如果不使用repro,很难知道这说明了多少问题。

代码语言:javascript
复制
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);
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-10-09 19:20:10

造成此错误的原因有两个

  1. 如果您使用IIS托管gRPC服务器,那么ISS中还不支持一些特性,因此使用Kestrel应该可以修复这个错误。
  2. 由@vivekDev解释Visual 2022预览中有一个bug,关闭Css的热版本应该可以修复这个错误
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63240268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档