序列化时尝试 post 使用 Protocol Buffers 序列化的数据失败
Attempting to post data serialized using Protocol Buffers fails when serializing
简述
尝试使用 Google 的 Protocol Buffers 序列化对象时出现以下错误:
Type is not expected, and no contract can be inferred:
更多详情
我有三个项目:
- 带有 *.proto 文件的 DotNet 标准 2.0 库项目
- DotNet 框架 4.8 WebAPI
- DotNet 5 测试应用程序
带有 *.proto 文件的 DotNet 标准 2.0 库项目
库包含一个 *.proto 文件。这包含几个不同的 message
对象,每个对象的属性要么是字符串,要么是 int32。有两个“包装器”对象,一个名为 Request
(另一个名为 Response
)。没有什么明显的复杂。
此库的 NuGet 包是:
<PackageReference Include="Google.Protobuf" Version="3.17.3" />
<PackageReference Include="Grpc" Version="2.40.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
可能有些是不必要的....
DotNet 框架 4.8 WebAPI
所以我的想法是我的 .NET 4.8 WebAPI 将接收 Request
对象(这是 proto 文件中定义的 类 之一)然后 return Response
对象(也在这个 proto 文件中定义)。
DotNet 5 测试应用程序
但是....我的测试在它有机会对 WebAPI 进行 Http 调用之前就失败了...
我的 .NET 5 测试项目具有以下 NuGet 包:
<PackageReference Include="protobuf-net" version="3.0.101" />
它还有一个对我的 .NET Standard 库的包引用(所以知道 Request
和 Response
,以及它拥有的 NuGet 包。
在我的测试中,我创建了一个新的 Request
对象(来自原型文件中定义的命名空间 SomeNamespace
)并填充它的属性。
然后我尝试使用以下方法对其进行序列化:
using MemoryStream stream = new();
ProtoBuf.Serializer.Serialize<Request>(stream, objectToBeSerialized);
这就是错误发生的地方:
System.InvalidOperationException
HResult=0x80131509
Message=Type is not expected, and no contract can be inferred: SomeNamespace.Request
Source=protobuf-net.Core
StackTrace:
at ProtoBuf.Internal.ThrowHelper.ThrowInvalidOperationException(String message, Exception innerException) in //src/protobuf-net.Core/Internal/ThrowHelper.cs:line 56
at ProtoBuf.Meta.TypeModel.ThrowUnexpectedType(Type type, TypeModel model) in //src/protobuf-net.Core/Meta/TypeModel.cs:line 1648
at ProtoBuf.Meta.TypeModel.SerializeRootFallback(State& state, Object value) in //src/protobuf-net.Core/Meta/TypeModel.cs:line 282
at ProtoBuf.Meta.TypeModel.SerializeImpl[T](State& state, T value) in //src/protobuf-net.Core/Meta/TypeModel.cs:line 358
at ProtoBuf.Serializer.Serialize[T](Stream destination, T instance, Object userState) in //src/protobuf-net/Serializer.Serialize.cs:line 33
at ProtoBuf.Serializer.Serialize[T](Stream destination, T instance) in //src/protobuf-net/Serializer.Serialize.cs:line 20
at TestNamespace.TempTests.d__0.MoveNext() in c:\SomePath\TempTests.cs:line 53
我不清楚为什么这可能会失败。
理想情况下,我想对最佳实践进行标准化,所以如果我没有使用理想的 NuGet 包,请告诉我。
在 protobuf 中,使用 .proto 时,涉及两套工具:
- 模式parser/code生成器
- 运行库
现在,我们还需要知道的是,在 .NET 领域中有多种 protobuf 实现;与这个问题相关的是 Google 实现和 protobuf-net(还有其他的,但它们与这个问题无关)。
我认为您所做的是:您在第 1 步中使用了 Google 工具(“protoc”),但在第 2 步中使用了 protobuf-net。1 和 2 的工具需要匹配: Google 和 Google 没问题; protobuf-net 和 protobuf-net 很好 - 但不是交叉。
所以,要么:
一个。使用 Google 运行时库而不是 protobuf-net(“Google.Protobuf”,作为 nuget 包),或者
b:使用 protobuf-net 的模式工具和代码生成器(参见 https://protobuf-net.github.io/protobuf-net/contract_first.html,包括底部的其他选项链接)
如果我的预感是正确的,请告诉我 - 我会尝试让 protobuf-net 识别这种情况并至少提供适当的指导
简述
尝试使用 Google 的 Protocol Buffers 序列化对象时出现以下错误:
Type is not expected, and no contract can be inferred:
更多详情
我有三个项目:
- 带有 *.proto 文件的 DotNet 标准 2.0 库项目
- DotNet 框架 4.8 WebAPI
- DotNet 5 测试应用程序
带有 *.proto 文件的 DotNet 标准 2.0 库项目
库包含一个 *.proto 文件。这包含几个不同的 message
对象,每个对象的属性要么是字符串,要么是 int32。有两个“包装器”对象,一个名为 Request
(另一个名为 Response
)。没有什么明显的复杂。
此库的 NuGet 包是:
<PackageReference Include="Google.Protobuf" Version="3.17.3" />
<PackageReference Include="Grpc" Version="2.40.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
可能有些是不必要的....
DotNet 框架 4.8 WebAPI
所以我的想法是我的 .NET 4.8 WebAPI 将接收 Request
对象(这是 proto 文件中定义的 类 之一)然后 return Response
对象(也在这个 proto 文件中定义)。
DotNet 5 测试应用程序
但是....我的测试在它有机会对 WebAPI 进行 Http 调用之前就失败了...
我的 .NET 5 测试项目具有以下 NuGet 包:
<PackageReference Include="protobuf-net" version="3.0.101" />
它还有一个对我的 .NET Standard 库的包引用(所以知道 Request
和 Response
,以及它拥有的 NuGet 包。
在我的测试中,我创建了一个新的 Request
对象(来自原型文件中定义的命名空间 SomeNamespace
)并填充它的属性。
然后我尝试使用以下方法对其进行序列化:
using MemoryStream stream = new();
ProtoBuf.Serializer.Serialize<Request>(stream, objectToBeSerialized);
这就是错误发生的地方:
System.InvalidOperationException HResult=0x80131509 Message=Type is not expected, and no contract can be inferred: SomeNamespace.Request Source=protobuf-net.Core StackTrace: at ProtoBuf.Internal.ThrowHelper.ThrowInvalidOperationException(String message, Exception innerException) in //src/protobuf-net.Core/Internal/ThrowHelper.cs:line 56 at ProtoBuf.Meta.TypeModel.ThrowUnexpectedType(Type type, TypeModel model) in //src/protobuf-net.Core/Meta/TypeModel.cs:line 1648 at ProtoBuf.Meta.TypeModel.SerializeRootFallback(State& state, Object value) in //src/protobuf-net.Core/Meta/TypeModel.cs:line 282 at ProtoBuf.Meta.TypeModel.SerializeImpl[T](State& state, T value) in //src/protobuf-net.Core/Meta/TypeModel.cs:line 358 at ProtoBuf.Serializer.Serialize[T](Stream destination, T instance, Object userState) in //src/protobuf-net/Serializer.Serialize.cs:line 33 at ProtoBuf.Serializer.Serialize[T](Stream destination, T instance) in //src/protobuf-net/Serializer.Serialize.cs:line 20 at TestNamespace.TempTests.d__0.MoveNext() in c:\SomePath\TempTests.cs:line 53
我不清楚为什么这可能会失败。
理想情况下,我想对最佳实践进行标准化,所以如果我没有使用理想的 NuGet 包,请告诉我。
在 protobuf 中,使用 .proto 时,涉及两套工具:
- 模式parser/code生成器
- 运行库
现在,我们还需要知道的是,在 .NET 领域中有多种 protobuf 实现;与这个问题相关的是 Google 实现和 protobuf-net(还有其他的,但它们与这个问题无关)。
我认为您所做的是:您在第 1 步中使用了 Google 工具(“protoc”),但在第 2 步中使用了 protobuf-net。1 和 2 的工具需要匹配: Google 和 Google 没问题; protobuf-net 和 protobuf-net 很好 - 但不是交叉。
所以,要么:
一个。使用 Google 运行时库而不是 protobuf-net(“Google.Protobuf”,作为 nuget 包),或者 b:使用 protobuf-net 的模式工具和代码生成器(参见 https://protobuf-net.github.io/protobuf-net/contract_first.html,包括底部的其他选项链接)
如果我的预感是正确的,请告诉我 - 我会尝试让 protobuf-net 识别这种情况并至少提供适当的指导