How Can I Connect To A Local WebSocket Server with Uno Platform WebAssembly - uno-platform

The following code works with UWP but not WASM. I do have the Uno.Wasm.WebSockets package installed on the WASM head.
_webSocketConnectionCTS = new CancellationTokenSource();
using (_webSocket = new ClientWebSocket())
{
try
{
await _webSocket.ConnectAsync(new Uri(address), _webSocketConnectionCTS.Token);
await Receive(_webSocket, _webSocketConnectionCTS.Token);
}
catch (Exception ex)
{
Console.WriteLine("Failed to connect to WebSocket server: " + ex.Message);
}
}
The exception is thrown on the connect: "Value cannot be null" but neither parameter is null.

The ClientWebSocket class is not available in current builds of Uno, as the underlying class is not providing an implementation for it. You can use the Uno.Wasm.WebSockets package instead, which uses the same APIs as ClientWebSocket.
Here's an example from the documentation:
var ws = new Uno.Wasm.WebSockets.WasmWebSocket();
// Connect to a simple echo WebSocket server
await ws.ConnectAsync(new Uri("wss://echo.websocket.org"), CancellationToken.None);
Console.WriteLine("Program: Connected!");
// Send some data
var data = new ArraySegment<byte>(Encoding.UTF8.GetBytes("Hello websocket !"));
await ws.SendAsync(data, System.Net.WebSockets.WebSocketMessageType.Binary, false, CancellationToken.None);
Console.WriteLine("Program: Sent!");
// Read the echo back
var buffer = new byte[1024];
var received = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
var receivedString = Encoding.UTF8.GetString(buffer, 0, received.Count);
Console.WriteLine($"Received {received.Count} bytes: {receivedString}");

Related

.NET CORE GRPC stream exception

I'm working on a .NET Core chat room using gRPC (BI Directional streaming).
client, for now, is a console app (.net core 3.1, server is 5.0).
client-server communication was working alright and suddenly, I started having RpcExceptions thrown.
the problem is, the exceptions thrown have StatusCode=OK and no details.
here is a code sample (simplified)
SERVER Stream RPC
if (!await requestStream.MoveNext())
return;
//Open Connection - set user stream to server's output
client.Stream = responseStream;
while(await requestStream.MoveNext())
{
var chatMessage = requestStream.Current;
chatMessage.Msg = $"{requestStream.Current.ClientName}: {requestStream.Current.Msg}";
foreach (var user in loggedClients)
{
user.Stream.WriteAsync(chatMessage);
}
}
Client Code
using (var streaming = client.RPC_BroadcastChatMessage(metaData))
{
//Read stream and display on console
var readTask = Task.Run(async () =>
{
while (await streaming.ResponseStream.MoveNext())
{
Console.WriteLine($"{streaming.ResponseStream.Current.Msg}");
}
});
//Send first message (empty string) - for a welcome message
Console.WriteLine("Sending empty msg");
await streaming.RequestStream.WriteAsync(emptyMsg);
//Wait for messages from user and send to server
Console.WriteLine("Type message and press Enter to send...");
string line = Console.ReadLine();
while (!string.Equals(line, "exit", StringComparison.OrdinalIgnoreCase))
{
var stream = streaming.RequestStream;
var msg = new ChatMessage()
{
ClientId = clientId,
ClientName = $"User{userNumber}",
Msg = line,
RoomId = roomId
};
await stream.WriteAsync(msg);
line = Console.ReadLine();
}
}
Exception
Grpc.Core.RpcException: Status(StatusCode="OK", Detail="")
both client and server run locally.
I've tried googling the exception but haven't found anything yet (not statusCode=OK related, anyways).
does anyone has any leads? I would very much appreciate it.

Signal R taking around 1 minute to connect to Hub in mobile network Xamarin forms

Below is my code to connect to the hub.
I used the below code for connecting the hub and send a message.
public ChatService(){
connection = new HubConnection(Services.ServerConstant.BaseUrl);
proxy = ChatServices._connection.CreateHubProxy("HubName");
}
//to start connection
Void async Start(){
var http = new Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient();
await _connection.Start(new WebSocketTransportLayer(http));
}
//For Connection
Void SendMessage(){
chatServices = DependencyService.Get<IChatServices>();
chatServices.Connect();
connection.Start();
await connection.Send("Test");
}
You are recreating connection to hub every time you send the message. That's wrong approach. Instead you should check connection status and reconnect only in case the connection is lost.
Example
private async Task CheckConnection()
{
if (connection.State == ConnectionState.Connected)
{
return;
}
try
{
await connection.Start();
await proxy.Invoke("Connect");
}
catch (Exception ex)
{
// your exception handler goes here
}
}

Actions on Google - Push Notifications in C#

I am trying to get a basic push notification sent to my Action.
I am getting an access token as such
private static async Task<string> GetAccessTokenFromJsonKeyAsync(string jsonKeyFilePath, params string[] scopes)
{
using (var stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read))
{
return await GoogleCredential
.FromStream(stream) // Loads key file
.CreateScoped(scopes) // Gathers scopes requested
.UnderlyingCredential // Gets the credentials
.GetAccessTokenForRequestAsync(); // Gets the Access Token
}
}
which returns me an access token.
I am then sending the following notification message
{
"customPushMessage": {
"userNotification":{
"title":"Notification Title"
},
"target":{
"userId":"ID_FROM_UPDATES_USER_ID",
"intent":"Notification Intent",
"locale":"en-US"
}
}
}
using the following code
try
{
var accessToken = await GetAccessTokenFromJsonKeyAsync("key.json", "https://www.googleapis.com/auth/actions.fulfillment.conversation");
var serialized = JsonConvert.SerializeObject(proactiveMessage);
var payload = "{\"customPushMessage\": " + serialized + "}";
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(payload, Encoding.UTF8, "application/json");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
var httpResponseMessage = await _httpClient.PostAsync("https://actions.googleapis.com/v2/conversations:send", httpContent);
Debug.WriteLine(httpResponseMessage.IsSuccessStatusCode ? "Successfully sent notification message." : $"Failed to send notification message with {httpResponseMessage.StatusCode}.");
return httpResponseMessage;
}
catch (Exception ex)
{
Debug.WriteLine($"Alexa API Service: Failed to send notification message with exception: {ex.Message}");
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
The response code I get is a 403 Forbidden.
I am not sure if the Access Token code is incorrect, the notification structure is incorrect, or if I am missing something else.
The token type needs to be "Bearer" with a capitol B. So that line should be
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
I was not requesting permission properly.This provided the missing piece of the puzzle for me.
Needed the
"updatePermission": {
"intent": "notification.simple.text"
}

Signup user to ASP.NET Identity from Xamarin

I have been stuck all day on a stupid problem with registering a user to my application.
Here is my code once the 'Register' button is clicked:
public ICommand RegisterCommand
{
get
{
return new Command(async() =>
{
var isSuccess = await _apiServices.RegisterAsync(Email, Password, ConfirmPassword);
if (isSuccess){
Message = "Registered Successfully";
}
else
{
Message = "Retry later";
}
});
}
}
Api services Register Async method:
public async Task<bool> RegisterAsync(string email, string password, string confirmPassword)
{
try
{
System.Diagnostics.Debug.WriteLine("Email: "+email);
var client = new HttpClient();
var model = new RegisterBindingModel
{
Email = email,
Password = password,
ConfirmPassword = confirmPassword
};
var json = JsonConvert.SerializeObject(model);
HttpContent content = new StringContent(json);
// content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.PostAsync("http://localhost:63724/api/Account/Register", content);
if (response.IsSuccessStatusCode)
{
return true;
}
return false;
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Error: "+e);
throw;
}
}
}
The Error that I get is:
System.Net.Http.HttpRequestException: An error occurred while sending the request ---> System.Net.WebException: Error: ConnectFailure (Connection refused) ---> System.Net.Sockets.SocketException: Connection refused
at System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP) [0x000b6] in <6c708cf596db438ebfc6b7e012659eee>:0
at System.Net.WebConnection.Connect (System.Net.HttpWebRequest request) [0x0016d] in <6c708cf596db438ebfc6b7e012659eee>:0
--- End of inner exception stack trace ---
To me this is very frustrating as I can register a use using Postman with the exact same localhost address. I am following Houssem Dellai's Xamarin.Forms mvc web api tutorials which can be found here
I had an issue with httpclient during the development of my app. I believe there was an issue with the cross-platform implementation of the httpclient class. iOS didn't know how to handle it.
Instead I implemented a very simple httpclient library called flurl: http://tmenier.github.io/Flurl/
First, you will need to install flurl in all project directories (iOS, Android, and the PCL) then the implementation is very simple.
using Flurl;
using Flurl.Http;
public async Task<User> CreateUserAsync(RegisterUserModel userModel)
{
string url = "your/backend/here";
//resp is a user object received and automatically converted into a c# object through the use of .ReceiveJson<typeofobject>();
var resp = await (url).PostJsonAsync(userModel)
.ReceiveJson<User>();
if (resp.LoginSession != null)
{
//Raise my registered event to let other classes know to proceed
OnUserRegistered(resp);
}
return resp;
}
As you can see it makes httpclient implementation very simple. Hopefully this helps.

How to describe an ASP.NET Web Service ENUM for JSR-172 (Java ME) Consumption

I have .NET Web Service and I am trying to use that web service from a Java Mobile phone. I am also using the NetBeans development environment with the web service tool kit. When I try to create the proxies, it falters on the enumerations stating that the simple types are not supported. Is there a way to describe the enumeration type in the WSDL so it is understandable to the toolkit?
// send a POST request to web server
public String sendPostRequest(String urlstring, String requeststring)
{
HttpConnection hc = null;
DataInputStream dis = null;
DataOutputStream dos = null;
String message = "";
// specifying the query string
String requeststring = "request=gettimestamp";
try
{
// openning up http connection with the web server
// for both read and write access
hc = (HttpConnection) Connector.open(urlstring, Connector.READ_WRITE);
// setting the request method to POST
hc.setRequestMethod(HttpConnection.POST);
hc.setRequestProperty("User-Agent","Profile/MIDP-2.0 Confirguration/CLDC-1.0");
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// obtaining output stream for sending query string
dos = hc.openDataOutputStream();
byte[] request_body = requeststring.getBytes();
// sending query string to web server
for (int i = 0; i < request_body.length; i++)
{
dos.writeByte(request_body[i]);
}
// flush outdos.flush();
// obtaining input stream for receiving HTTP response
dis = new DataInputStream(hc.openInputStream());
// reading the response from web server character by character
int ch;
while ((ch = dis.read()) != -1)
{
message = message + (char) ch;
}
}
catch (IOException ioe){
message = "ERROR";
}
finally{
// freeing up i/o streams and http connection
try{
if (hc != null)
hc.close();
}
catch (IOException ignored){}
try{
if (dis != null)
dis.close();
}
catch (IOException ignored){}
try{
if (dos != null)
dos.close();
}
catch (IOException ignored){}
}
return message;
}

Resources