gRPC service calls in Windows Forms .NET Framework 4.8 client

61 Views Asked by At

I am starting with gRPC and maybe anybody can help me with the following issue:

I have a Windows Form in a .NET Framework 4.8 platform and I want to call a service when, for example, I click a button.

To try it, I have create a Server in Visual Studio in ASP.NET Core 3.1, created the .proto file (in a Protos folder) with a simple service and message definition

syntax = "proto3";

option csharp_namespace = "Servidor_gRPC";

service Test {
    rpc Communication(QueryRequest) returns (QueryResponse);
}

message MyRequest {
    string message = 1;
}

message MyResponse {
    string message = 1;

then I right-click over the file and set Action = Protbuf compiler and gRPC Stub Classes = Server only.

I build the project and I see Test.cs and TestGrpc.cs classes are created in C:...\Server_gRPC\Server_gRPC\obj\Debug\netcoreapp3.1 folder.

Now I implement the service in TestService.cs:

using Grpc.Core;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace Servidor_gRPC
{
    public class TestService : Test.TestBase
    {
        private readonly ILogger<TestService> _logger;
        public TestService(ILogger<TestService> logger)
        {
            _logger = logger;
        }

        public override Task<MyResponse> Communication(MyRequest request, ServerCallContext context)
        {
            return Task.FromResult(new MyResponse
            {
                Message = "Server received the following client message: " + request.Message
            });
        }
    }
}

Now I would create the service in an existing Windows Forms project (in .NET Framework 4.8) by adding the service with a right click mouse button on the client project to get something like:

setting gRPC Service in Cliente

but I can't add service in this way in my Windows Form project in this .NET Framework platform client. It doesn't give me the option show in the image before, I understand, due to compability:

gRPC compatibility

I have Windows 10 Pro (in my work), so I can't use WinHttpHandler and, for this reason, gRPC 'basic library' to get services. Then I check gRPC-Web following the Configure gRPC-Web with the .NET gRPC client. As it was hard for me to understand all that the link before was explained (and it seems it is more oriented to browsers in web, I can be of course wrong), I followed also this video about gRPC-Web with .NET (done by the person who create the gRPC-Web library)

I tried the following:

First, I tried to create a .proto file in the client with the same info set in the server. I create a Fodler 'Protos' and I try to add a Protobufer file, but it was not any existing file option in my Visual Studio 2019. I just made a copy of the .proto file in the server and I changed the namespace for that in the client (WinForm_gRPC):

syntax = "proto3";

option csharp_namespace = "WinForm_gRPC";

service Test {
    rpc Communication(MyRequest) returns (MyResponse);
}

message MyRequest {
    string message = 1;
}

message MyResponse {
    string message = 1;
}

Then I build the client project and get the classes expected: Test.cs and TestGrpc.cs were built and placed in C:...\WinForm_gRPC\WinForm_gRPC\obj\Debug\Protos folder.

Now, I install Grpc.NetClient.Web 2.61.0 with NuGet.

With the Test classes generated and the library, I put the next code to make the call to the server:

private void btnLogin_Click(object sender, EventArgs e)
        {
            Uri backendUrl = new Uri("http://localhost:5001");
            var httpHandler = new GrpcWebHandler(GrpcWebMode.GrpcWebText, new HttpClientHandler());
            var c = GrpcChannel.ForAddress(backendUrl, new GrpcChannelOptions { HttpHandler = httpHandler });            
            var client = new Test.TestClient(c);            

            MyRequest myRequest = new MyRequest();
            myRequest.Message = "Control message";
            
            try
            {
                var response = client.Communication(myRequest);
            } catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }            
        }

I build the project and then run it, but in the sentence

var response = client2.Communication(myRequest);

I get the exception:

InnerException: "Error sending the request"

Source: "mscorlib"

Message: Status(StatusCode="Internal", Detail="Error starting gRPC call. 
HttpRequestException: Error sending the request. 
WebException: The connection has been terminated unexpectedly.",
DebugException="System.Net.Http.HttpRequestException: Error sending the request.")

StackTrace: en System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   en System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   en Grpc.Net.Client.Internal.GrpcCall`2.<GetResponseHeadersCoreAsync>d__72.MoveNext()
   en System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   en System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   en Grpc.Net.Client.Internal.HttpClientCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request)
   en Grpc.Core.Interceptors.InterceptingCallInvoker.<BlockingUnaryCall>b__3_0[TRequest,TResponse](TRequest req, ClientInterceptorContext`2 ctx)
   en Grpc.Core.ClientBase.ClientBaseConfiguration.ClientBaseConfigurationInterceptor.BlockingUnaryCall[TRequest,TResponse](TRequest request, ClientInterceptorContext`2 context, BlockingUnaryCallContinuation`2 continuation)
   en Grpc.Core.Interceptors.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request)
   en WinForm_gRPC.Test.TestClient.Communication(MyRequest request, CallOptions options) en C:\Users\2590\source\repos\WinForm_gRPC\WinForm_gRPC\obj\Debug\Protos\TestGrpc.cs: línea 114
   en WinForm_gRPC.Test.TestClient.Communication(MyRequest request, Metadata headers, Nullable`1 deadline, CancellationToken cancellationToken) en C:\Users\2590\source\repos\WinForm_gRPC\WinForm_gRPC\obj\Debug\Protos\TestGrpc.cs: línea 109
   en WinForm_gRPC.Form1.btnLogin_Click(Object sender, EventArgs e) en C:\Users\2590\source\repos\WinForm_gRPC\WinForm_gRPC\Form1.cs: línea 135

TargetSite: {Void ThrowForNonSuccess(System.Threading.Tasks.Task)}

Trailers: Count = 0, IsReadOnly = true

This is the furthest point I could reach. My questions are:

  • Is it possible to use any gRPC service (basic o web) with a Windows Form project in .NET Framework 4.8 platform?
  • If it is possible, where did I failed?

I tried this thread: How do you create a gRPC client in .NET Framework?, but it didn't help me (or I didn't know how to integrate that in my issue)

Thank you for your time!

0

There are 0 best solutions below