Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrating .NET 7 to 8 with gRPC - No marshaller available for Dictionary<string, string> #336

Closed
japtar10101 opened this issue Sep 24, 2024 · 1 comment

Comments

@japtar10101
Copy link

When upgrading a working .NET 7 project using gRPC service to .NET 8, following the Update a Blazor WebAssembly app guide, running the code under Docker causes the following error to appear on the browser console:

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: TypeInitialization_Type, DefaultProxyCache`1
System.TypeInitializationException: TypeInitialization_Type, DefaultProxyCache`1
 ---> System.Reflection.TargetInvocationException: Arg_TargetInvocationException
 ---> System.InvalidOperationException: No marshaller available for System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
   at ProtoBuf.Grpc.Internal.MarshallerCache.<GetMarshaller>g__Throw|5_0[Dictionary`2]()
   at ProtoBuf.Grpc.Internal.MarshallerCache.GetMarshaller[Dictionary`2]()
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object , BindingFlags )
   Exception_EndOfInnerExceptionStack
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object , BindingFlags )
   at System.Reflection.RuntimeMethodInfo.Invoke(Object , BindingFlags , Binder , Object[] , CultureInfo )
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at ProtoBuf.Grpc.Internal.ProxyEmitter.<EmitFactory>g__Marshaller|11_0[IDictionaryService](Type forType, <>c__DisplayClass11_0`1& , <>c__DisplayClass11_1`1& )
   at ProtoBuf.Grpc.Internal.ProxyEmitter.EmitFactory[IDictionaryService](BinderConfiguration binderConfig)
   at ProtoBuf.Grpc.Internal.ProxyEmitter.CreateFactory[IDictionaryService](BinderConfiguration binderConfig)
   at ProtoBuf.Grpc.Configuration.ClientFactory.DefaultProxyCache`1[[TestGrpc7.Client.Services.IDictionaryService, TestGrpc7.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]..cctor()
   Exception_EndOfInnerExceptionStack
   at ProtoBuf.Grpc.Configuration.ClientFactory.DefaultClientFactory.CreateClient[IDictionaryService](CallInvoker channel)
   at Program.<>c.<<Main>$>b__0_1(IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite , RuntimeResolverContext )
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite , RuntimeResolverContext )
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite , RuntimeResolverContext , ServiceProviderEngineScope , RuntimeResolverLock )
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite , RuntimeResolverContext )
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, RuntimeResolverContext argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite , ServiceProviderEngineScope )
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine.<>c__DisplayClass4_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier , ServiceProviderEngineScope )
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type )
   at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass9_0.<CreatePropertyInjector>g__Initialize|1(IServiceProvider serviceProvider, IComponent component)
   at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider , Type , IComponentRenderMode , Nullable`1 )
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame[] , Int32 , Int32 )
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& , Int32 )
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& , Int32 )
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& , Int32 )
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer , RenderBatchBuilder , Int32 , ArrayRange`1 , ArrayRange`1 )
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder , RenderFragment , Exception& )
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry )
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()

Some extra details:

  • The .NET 8 version of the project does run fine under Visual Studio 2022, Debug config.
  • According to my colleague, they were able to get a similar result with dotnet TestGrpc7.Server.dll, so we believe Docker isn't the source of the problem
  • There is this documentation page on .NET 8: Breaking Changes: Custom marshallers require additional members.

Expected Behavior

When running the attached projects in Docker, a web page will show up, indicating the base address of the website (e.g. http://localhost:8080/), as well as a table with key value pairs of:

Keys Values
Hello World
Greetings Nice to meet you, "[base address]"

Steps To Reproduce

The following steps was replicated in Windows 10 Powershell terminal:

  1. Download, then extract the source code below:
  2. At the root of each project (where the Dockerfile is), run: docker build -t test-grpc-7:net8 . This may take a few minutes.
  3. Once the build is finished, run docker run -p 127.0.0.1:8080:8080 test-grpc-7:net8.
  4. Open a web browser (e.g. Chrome or Edge), and navigate to localhost:8080.

The net7-grpc-dictionary-bug-1.1.1-net7.zip -- the original .NET 7 version of the same project above -- has been uploaded as well for comparison. Running all the steps above with the .NET 7 version of the project, except changing the version of each docker build from :net8 to :net7, should open the webpage described in the Expected Behavior section without error.

protobuf-net.Grpc.AspNetCore Version

1.1.1

Visual Studio 2022 version

17.10.6

Docker version

> docker --version
Docker version 27.2.0, build 3ab4256

Dotnet Info

> dotnet --info
.NET SDK:
 Version:           8.0.304
 Commit:            352dc5a01f
 Workload version:  8.0.300-manifests.113cb230
 MSBuild version:   17.10.4+10fbfbf2e

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.304\

.NET workloads installed:
 [wasm-tools]
   Installation Source: VS 17.10.35201.131
   Manifest Version:    8.0.8/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.workload.mono.toolchain.current\8.0.8\WorkloadManifest.json
   Install Type:        FileBased


Host:
  Version:      8.0.8
  Architecture: x64
  Commit:       08338fcaa5

.NET SDKs installed:
  2.2.109 [C:\Program Files\dotnet\sdk]
  5.0.416 [C:\Program Files\dotnet\sdk]
  7.0.410 [C:\Program Files\dotnet\sdk]
  8.0.304 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.33 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.33 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.33 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download
@mgravell
Copy link
Member

gRPC is limited to a few scenarios, and to avoid ambiguity the library doesn't try to play too loose with that fact; rather than trying to send a dictionary, send a simple DTO that has a dictionary

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants