Ajax 调用 Web Api 的方法使用 gRPC 服务(如何从数据库中获取列表?):错误 415 和 400

Ajax method calling a Web Api who its consuming a gRPC Service (how to get a list from a db?): Errors 415 and 400

我的 Web 控制台有问题,首先它在 ajax 方法中没有 contentType: 'application/json; charset=UTF-8', 时给我错误 415,然后给我错误 400。

如果错误出现在后端代码中,我也会尝试进行调试,但它从未发生并且会跳出(这没有任何意义,调试器应该 运行...)

我的目标是 return 用户列表和他们的电子邮件,类似这样

//在我的服务中尝试这样做
IEnumerable()

//classc#
显示用户:
(字符串)用户名:User1
(字符串)电子邮件:user1@example.com

但我在 gRPC 中执行此操作,因此我将有一个 Web API 控制器调用 gRPC 方法

由于gRPC中没有IEnumerable,所以我的proto和method是这样的:

原型:

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 方法服务 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);
        }

下面的代码是正确的(我用 POST 方法测试控制器和 ajax 我在没有 gRPC 的情况下测试并且工作正常)但是你会明白我的意思我正在做(它的控制器和 ajax 方法)

控制器[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方法:

$(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>');
            }
        });
    });


欢迎任何帮助

A bi-directional 流式 RPC 将是更好的选择,因为它将 显着提高您的表现并可能解决您的问题。

您需要按以下方式更改原型:

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 方法服务 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()
                });
            }
        }

在客户端:

    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;
    }

客户端对象来自从 gRPC 服务创建的通道 URL(我假设您知道)。 现在你可以把它变成一个服务,并通过你的控制器的依赖注入来调用它。 我没有测试它,所以它可能有一些编译错误,但方法是正确的。