.net grpc client event store and docker

Hello

I am following the following documentation
https://developers.eventstore.com/server/20.6/server/installation/docker.html#use-docker-compose

My expectation is to have ES to allow grpc connections

I am also following the following:
https://developers.eventstore.com/clients/dotnet/generated/v20.6.1/connecting/di-extensions.html

How can I get the connection string to work with it. I am getting an error at the moment

what error are you getting?

System.ArgumentException: ‘Only ‘http’ and ‘https’ schemes are allowed. (Parameter ‘requestUri’)’

I have the following:
esdb://localhost:2113?tls=false

My bet is you are trying to use the connection string where it asks for the url. Try the following

var settings = EventStoreClientSettings
.Create("<connection string goes here>");
var client   = new EventStoreClient(settings);

Yeah, how can I use the dependency injection extension method?

I will give this a go and see if it works
services.AddEventStoreClient(settings => { settings = EventStoreClientSettings.Create(eventStoreConfiguration.ConnectionString); settings.DefaultCredentials = new UserCredentials(eventStoreConfiguration.Username, eventStoreConfiguration.Password); settings.CreateHttpMessageHandler = () => new SocketsHttpHandler { SslOptions = { RemoteCertificateValidationCallback = delegate { return true; } } }; });

System.InvalidOperationException
HResult=0x80131509
Message=Status(StatusCode=Internal, Detail=“Request protocol ‘HTTP/1.1’ is not supported.”)
Source=EventStore.Client
StackTrace:
at EventStore.Client.Interceptors.TypedExceptionInterceptor.AsyncStreamReader1.<MoveNext>d__4.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at Grpc.Core.AsyncStreamReaderExtensions.<ReadAllAsync>d__01.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore1.GetResult(Int16 token) at Grpc.Core.AsyncStreamReaderExtensions.<ReadAllAsync>d__01.System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult(Int16 token)
at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1.ConfiguredValueTaskAwaiter.GetResult() at EventStore.Client.EventStoreClient.ReadStreamResult.<>c__DisplayClass4_0.<<-ctor>g__GetStateInternal|0>d.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at EventStore.Client.EventStoreClient.ReadStreamResult.<MoveNextAsync>d__10.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ValueTaskAwaiter1.GetResult()
at Foundation.Cqrs.Repository.EventStore.EventstoreEventStorageProvider.d__51.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Foundation.Cqrs.Repository.EventStore.EventstoreEventStorageProvider.<ReadStreamEventsForwardAsync>d__51.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Foundation.Cqrs.Repository.EventStore.EventstoreEventStorageProvider.d__51.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore1.GetResult(Int16 token)
at Foundation.Cqrs.Repository.EventStore.EventstoreEventStorageProvider.d__51.System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult(Int16 token) at System.Runtime.CompilerServices.ValueTaskAwaiter1.GetResult()
at Foundation.Cqrs.Aggregate.SnapshotAggregateRoot2.<LoadFromHistory>d__15.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Foundation.Cqrs.Aggregate.SnapshotAggregateRoot2.d__15.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Foundation.Cqrs.Repository.SnapshotRepositoryDecorator.d__21.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at AccountService.Command.ApplicationService.HandleMessagesBaseHandler`2.d__4.MoveNext() in C:\connectbz\accountservice\src\Command\AccountService.Command.ApplicationService\HandleMessagesBaseHandler.cs:line 34

This exception was originally thrown at this call stack:
[External Code]

Inner Exception 1:
RpcException: Status(StatusCode=Internal, Detail=“Request protocol ‘HTTP/1.1’ is not supported.”)

services.AddSingleton(sp =>
{
var eventStoreClientSettings = EventStoreClientSettings.Create(eventStoreConfiguration.ConnectionString);
eventStoreClientSettings.DefaultCredentials = new UserCredentials(eventStoreConfiguration.Username, eventStoreConfiguration.Password);

            return new EventStoreClient(eventStoreClientSettings);
        });

that does not work… throws the exception above :frowning_face:

Please paste your docker command line

https://developers.eventstore.com/server/20.6/server/installation/docker.html#use-docker-compose

Using that from ES docs

@Joao_Braganca any feedback?

There are two examples on that page and they are both docker compose, as the connection string esdb://localhost:2113?tls=false is only compatible with one of them. You’ll have to be more specific.

This yaml. taken directly from ES docs

`version: ‘3.4’

services:
eventstore.db:
image: eventstore/eventstore:20.6.1-buster-slim
environment:
- EVENTSTORE_CLUSTER_SIZE=1
- EVENTSTORE_RUN_PROJECTIONS=All
- EVENTSTORE_START_STANDARD_PROJECTIONS=true
- EVENTSTORE_EXT_TCP_PORT=1113
- EVENTSTORE_EXT_HTTP_PORT=2113
- EVENTSTORE_INSECURE=true
- EVENTSTORE_ENABLE_EXTERNAL_TCP=true
- EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true
ports:
- “1113:1113”
- “2113:2113”
volumes:
- type: volume
source: eventstore-volume-data
target: /var/lib/eventstore
- type: volume
source: eventstore-volume-logs
target: /var/log/eventstore

volumes:
eventstore-volume-data:
eventstore-volume-logs:

`

I started a node with your docker compose file, then wrote this small program:

	internal class Program {
		public static async Task<int> Main(string[] args) {
			var provider = new ServiceCollection().AddSingleton(_ =>
				new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113?tls=false")))
				.BuildServiceProvider();
			var client = provider.GetRequiredService<EventStoreClient>();
			var e = await client.ReadAllAsync(Direction.Forwards, Position.Start, 1)
				.FirstAsync();
			await Console.Out.WriteLineAsync(new {
				e.Event.EventStreamId,
				e.Event.EventNumber,
				e.Event.EventType
			}.ToString());
			return 0;
		}
	}

I omitted credentials here, as they will not be used when insecure=true. Here is the output:

{ EventStreamId = $projections-$all, EventNumber = 0, EventType = $ProjectionsInitialized }

Are you calling AppContext.SetSwitch in your code anywhere? The dotnet client will call AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true) to make unencrypted HTTP/2 work. Changing this to false can cause this error.

The docker yaml is from ES docs. It’s not mine.

For some reason it is not working for me…

No, I am not calling this line
AppContext.SetSwitch

Something else it could be. Is this project netcoreapp3.1 or net5? If it is net5, you will have to upgrade the Grpc.Net.Client package to the latest:

@ekjuanrejon were you able to find the solution?

Yes. I was able to. The site was not allowing me to post. It said I had reached the maximum number of post 13.

I have migrated my services to use grpc…

However I notice that in the dashboard the GRPC connections do not appear… It list 0 connections

Great that you were able to get everything working!

It list 0 connections

This is due to HTTP/2 as the transport for gRPC. You would not have seen ‘connections’ for people reading streams via ATOM, either.

As Joao said, the gRPC client doesn’t have the always-on connection, unlike the TCP connection. Hence the difference in the API semantics as we use the word Client. It connects when required only, similar to MongoDB client.