I've standart project HelloWorld in .net 5 to send grpc request and show in console the result.
This is my GrpcHelloWorldServer :
Program.cs :
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel(options =>
{
options.ListenLocalhost(5001, o =>
{
o.Protocols = HttpProtocols.Http2;
o.UseHttps(Get());
});
options.ListenLocalhost(5000, o =>
{
o.Protocols = HttpProtocols.Http2;
});
});
webBuilder.UseStartup<Startup>();
});
My method Get Get certificate :
public static X509Certificate2 Get()
{
var assembly = typeof(Program).GetTypeInfo().Assembly;
using (var stream = assembly.GetManifestResourceStream("GrpcHelloWorldServer.Certificate.translator.pfx"))
{
return new X509Certificate2(ReadStream(stream), "secret", X509KeyStorageFlags.MachineKeySet);
}
}
In startup in ConfigureSerices method I use services.AddGrpc();
and in Configure method I've
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<TestMyService>();
});
On client side main method is simple :
static async Task Main(string[] args)
{
try
{
// wait for grpc server is running
Console.WriteLine("Waiting for server is running");
Thread.Sleep(2000);
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var pem = File.ReadAllText(@"my certificate.pem");
var certData = GetBytesFromPem(pem, "CERTIFICATE");
var cert = new X509Certificate2(certData);
httpClientHandler.ClientCertificates.Add(cert);
var httpClient = new HttpClient(httpClientHandler);
var grpcChannel = GrpcChannel.ForAddress("https:myserverName:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new TestService.TestServiceClient(grpcChannel);
var response = await client.TestHelloAsync(new TestRequest { Name = "Julien" });
Console.WriteLine("Press any key to exit...");
Console.WriteLine(response.Message);
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
On local on my machine it's works perfectly. But on my Windows Server 2019 grpc request throw 2 exceptions :
For http request :
quote Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1)." quote
And for https request :
quote Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch", DebugException="System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch quote
My IIS configuration is :
So I don't understand why it's working fine on local and not on IIS ?
UPDATE
I add certificate on server and client side, but on my server error is :
Exception Info: System.InvalidOperationException: Application is running inside IIS process but is not configured to use IIS server.
So if I remove UseKestrel in Program.cs and add
webBuilder.UseStartup<Startup>().ConfigureKestrel((context, options) =>
{
options.ListenLocalhost(5001, o =>
{
o.Protocols = HttpProtocols.Http2;
o.UseHttps(Get());
});
options.ListenLocalhost(5000, o =>
{
o.Protocols = HttpProtocols.Http2;
});
});
, IIS throw another exception :
System.InvalidOperationException: Trailers are not supported for this response. The server may not support gRPC.