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.