Home > database >  Ajax method calling a Web Api who its consuming a gRPC Service (how to get a list from a db?): Error
Ajax method calling a Web Api who its consuming a gRPC Service (how to get a list from a db?): Error

Time:05-31

I have problems in my web console, first it gives me error 415 without contentType: 'application/json; charset=UTF-8', in ajax method and with it gives me error 400.

I also try doing debug if the error is in backend code but it never happens and it jumps off (this don't make any sense, the debugger should run...)

My goal is to return a list of users and their email, something like this

//trying to do this in my service
IEnumerable()

//class c#
ShowUsers:
(string)Username: User1
(string)Email:[email protected]

But I'm doing this in gRPC, so I'll have a web API controller calling the gRPC method

As there is no IEnumerable in gRPC, so my proto and method look like this:

Proto:

syntax = "proto3";

option csharp_namespace = "GrpcService1.Protos";

package UserAuth;

service UserAuth {
rpc GetAllUsers(MessageRequest) returns(ListUsersResponse);
}

message ListUserResponse{
     string username = 1;
     string email = 2;
}

message ListUsersResponse{
  repeated ListUserResponse lstUsers = 1;
}

message MessageRequest{
string message = 1;
}

gRPC method service c#

public override Task<ListUsersResponse> GetAllUsers(MessageRequest request, ServerCallContext context)
        {
            //This gives me an IEnumerable<ShowUsers> (this is
            correct)
            var a = _userBll.getAllUsers();

           //Here in this lines maybe be the problem but I don't
           //know where (maybe be because of json type or something into a list)
           //here im trying to put separate list of users and emails
            var names = a.Select(x => x.Username);
            var emails = a.Select(y => y.Email);

            //here im trying to put the lists into a Response
            var all = new ListUserResponse
            {
                Username = names.ToString(),
                Email = emails.ToString()
            };

            //the above will give the same but the
            ListUsersResponse is a repeated attribute
            var response = new ListUsersResponse
            {
                LstUsers = { all }
            };

            //all ok
            request.Message = "Sucess";

            return Task.FromResult(response);
        }

The code below is correct (I test with a POST method the controller and the ajax I test without the gRPC and works fine) but you will have the idea of ​​what I'm doing (its the controller and the ajax method)

Controller [HTTPGET]:

[HttpGet("getAllUserInfo_2"), Authorize]
        public async Task<ActionResult<ListUsersResponse>> GetAll_2([FromBody] MessageRequest message)
        {
            _logger.Log(LogLevel.Information, "Request Received for AuthController::Register");

            var results = await _userClient.GetAllUsersAsync(message);

            _logger.Log(LogLevel.Information, "Sending Response from AuthController::Register");

            return Ok(results);
        }

Ajax Method:

$(function b() {
    debugger;
    var $users_A = $('#users_A');
    $.ajax({
            contentType: 'application/json; charset=UTF-8', //if I comment this gives me 415
            url: uri_3_2,
            type: 'GET',
            dataType: 'json',
            beforeSend: function(request) {
                request.setRequestHeader("Authorization", 'Bearer '   localStorage.getItem("key"));
            },
            success: function(date) {
                $.each(data, function (i, rice) {
                    $users_A.append('<li>Name: '   arroz.username   ' Email: '   arroz.email   ' </li>');
                });
            },
            error: function (xhr, textStatus, errorThrown) {
                console.log('XHR:'   xhr   '\nTextStatus:'   textStatus   '\nErrorThrown:'   errorThrown);   //this should give me more info about the error but don't works... But it 
                //works fine the implementation code
                $users_A.append('<h4>ERRRROORRRR</h4>');
            }
        });
    });


Any help is welcome

CodePudding user response:

A bi-directional streaming RPC would be a better option as it will improve your performance significantly and may solve your problem.

you need to change your proto as the following:

syntax = "proto3";
option csharp_namespace = "GrpcService1.Protos";
package UserAuth;

service UserAuth {
rpc GetAllUsers(MessageRequest) returns(stream UserResponse);
}

message UserResponse{
     string username = 1;
     string email = 2;
}

message MessageRequest{
     string message = 1;
}

gRPC method service c#

public override async Task GetAllUsers(MessageRequest request, IServerStreamWriter<UserResponse> responseStream, ServerCallContext context)
        {
            var users = _userBll.getAllUsers();
            foreach (user in users)
            {
                await responseStream.WriteAsync(new UserResponse
                {
                    Username = user.Username.ToString(),
                    Email = user.Email.ToString()
                });
            }
        }

in client:

    public async Task<List<UserResponse> GetAllUsers()
    {
        var userResponseList = new List<UserResponse>();
        using var call = client.GetAllUsers(new MessageRequest());
        while (await call.ResponseStream.MoveNext())
        {
            var userResponse = new UserResponse
                {
                    Username = call.ResponseStream.Current.Username,
                    Email = call.ResponseStream.Current.Email
                });
            userResponseList.Add(userResponse);
        }
        return userResponseList;
    }

the client object has come from the channel which is created from the gRPC service URL (I assume you know it). Now you can make this a service and call it by dependency injection from your controller. I didn't test it so it may have some compile errors but the approach is correct.

  • Related