我正在.NET Core3.1上运行一个.NET服务,并试图从.NET Framework4.7.2客户端进行调用。我正在使用protobuf来重用现有的WCF数据契约。今天,当响应对象的一个字段为非空时,我注意到了以下意外的客户端行为。
Grpc.Core.RpcException: 'Status(StatusCode="Internal", Detail="Failed to deserialize response message.")
这里有一个示例说明了数据契约的一般结构--在本例中,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
}让我沮丧的是,我在其他数据契约中使用了类似或相同的模式,在反序列化响应时不会抛出异常。我进行了一些搜索,发现这一期从2019年开始将不同的Google.Protobuf版本作为可能的错误来源(但这里似乎并非如此)。
以前有人见过这个异常吗?我不确定这是我的数据契约的问题,还是包版本错配的问题。任何想法或建议都非常感谢!
我还尝试更新到protobuf v3.0.0,但是对于每个客户端调用都得到了一个新的客户端异常:,这似乎是一个不同的问题,我目前的猜测是,这可能与protobuf网v3中的破坏更改re:动态类型有关。
发布于 2021-09-16 07:39:03
我正在使用VisualStudio2022预览,我正面临这个问题。
正如前面提到的这里,VisualStudio2022中有一个bug。
我应用了下面提到的工作,它为我工作。请看下面的屏幕截图。
将“热重新发布CSS更改”设置为false,如下所示。


发布于 2020-08-04 06:48:46
坦率地说,这听起来像是protobuf-net中的一个bug,您应该登录到GitHub上,最好是使用同时显示服务契约(接口)的repro。
类型应该看上去很合理。最后的长度错配特别令人震惊,但我不认为这与动态类型讨论有任何关系。
很高兴在这里帮助调查(我是作者),但是:这听起来更像是一个GitHub的东西。
我怀疑,长度差异与Data不是原始合同有关(因此,对于原始包含是否得到尊重是有疑问的;这是由var强化的,如果有重复字段1的话),但是适当的复制确实会有所帮助。
下面的代码似乎有效--对代码的唯一更改是确保Data被标记为ProtoContract,对“包含”部分使用不同的数字,并向PersonDataItem添加一个Create方法以供测试工具使用;如果不使用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);
}
}发布于 2021-10-09 19:20:10
造成此错误的原因有两个
https://stackoverflow.com/questions/63240268
复制相似问题